killbill-aplcache

Ongoing work on 1.0 APIs

4/27/2012 11:32:28 PM

Changes

jaxrs/src/test/java/com/ning/billing/jaxrs/json/TestJsonViews.java 340(+0 -340)

Details

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 e4a8f43..e7bcd9a 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
@@ -27,7 +27,7 @@ import org.testng.Assert;
 
 import com.google.common.base.Joiner;
 import com.google.common.eventbus.Subscribe;
-import com.ning.billing.entitlement.api.repair.RepairEntitlementEvent;
+import com.ning.billing.entitlement.api.timeline.RepairEntitlementEvent;
 import com.ning.billing.entitlement.api.user.SubscriptionEventTransition;
 import com.ning.billing.invoice.api.InvoiceCreationEvent;
 import com.ning.billing.payment.api.PaymentErrorEvent;
diff --git a/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestIntegrationBase.java b/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestIntegrationBase.java
index cc4aae3..9f13f4d 100644
--- a/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestIntegrationBase.java
+++ b/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestIntegrationBase.java
@@ -49,7 +49,7 @@ import com.ning.billing.beatrix.lifecycle.Lifecycle;
 import com.ning.billing.catalog.api.Currency;
 import com.ning.billing.dbi.MysqlTestingHelper;
 import com.ning.billing.entitlement.api.EntitlementService;
-import com.ning.billing.entitlement.api.repair.EntitlementRepairApi;
+import com.ning.billing.entitlement.api.timeline.EntitlementTimelineApi;
 import com.ning.billing.entitlement.api.user.EntitlementUserApi;
 import com.ning.billing.entitlement.api.user.SubscriptionData;
 import com.ning.billing.invoice.api.Invoice;
@@ -108,7 +108,7 @@ public class TestIntegrationBase implements TestFailure {
     protected EntitlementUserApi entitlementUserApi;
 
     @Inject
-    protected EntitlementRepairApi repairApi;
+    protected EntitlementTimelineApi repairApi;
     
     @Inject
     protected InvoiceUserApi invoiceUserApi;
diff --git a/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestRepairIntegration.java b/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestRepairIntegration.java
index bae9197..4f23b48 100644
--- a/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestRepairIntegration.java
+++ b/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestRepairIntegration.java
@@ -39,11 +39,11 @@ import com.ning.billing.catalog.api.PlanPhaseSpecifier;
 import com.ning.billing.catalog.api.PriceListSet;
 import com.ning.billing.catalog.api.ProductCategory;
 import com.ning.billing.entitlement.api.SubscriptionTransitionType;
-import com.ning.billing.entitlement.api.repair.BundleRepair;
-import com.ning.billing.entitlement.api.repair.SubscriptionRepair;
-import com.ning.billing.entitlement.api.repair.SubscriptionRepair.DeletedEvent;
-import com.ning.billing.entitlement.api.repair.SubscriptionRepair.ExistingEvent;
-import com.ning.billing.entitlement.api.repair.SubscriptionRepair.NewEvent;
+import com.ning.billing.entitlement.api.timeline.BundleTimeline;
+import com.ning.billing.entitlement.api.timeline.SubscriptionTimeline;
+import com.ning.billing.entitlement.api.timeline.SubscriptionTimeline.DeletedEvent;
+import com.ning.billing.entitlement.api.timeline.SubscriptionTimeline.ExistingEvent;
+import com.ning.billing.entitlement.api.timeline.SubscriptionTimeline.NewEvent;
 import com.ning.billing.entitlement.api.user.SubscriptionBundle;
 import com.ning.billing.entitlement.api.user.SubscriptionData;
 import com.ning.billing.entitlement.api.user.SubscriptionEvents;
@@ -120,22 +120,22 @@ public class TestRepairIntegration extends TestIntegrationBase {
         }
         boolean ifRepair = false;
         if (ifRepair) {
-            BundleRepair bundleRepair = repairApi.getBundleRepair(bundle.getId());
+            BundleTimeline bundleRepair = repairApi.getBundleRepair(bundle.getId());
             sortEventsOnBundle(bundleRepair);
 
             // Quick check
-            SubscriptionRepair bpRepair = getSubscriptionRepair(baseSubscription.getId(), bundleRepair);
+            SubscriptionTimeline bpRepair = getSubscriptionRepair(baseSubscription.getId(), bundleRepair);
             assertEquals(bpRepair.getExistingEvents().size(), 2);
 
-            SubscriptionRepair aoRepair = getSubscriptionRepair(aoSubscription.getId(), bundleRepair);
+            SubscriptionTimeline aoRepair = getSubscriptionRepair(aoSubscription.getId(), bundleRepair);
             assertEquals(aoRepair.getExistingEvents().size(), 2);
 
-            SubscriptionRepair aoRepair2 = getSubscriptionRepair(aoSubscription2.getId(), bundleRepair);
+            SubscriptionTimeline aoRepair2 = getSubscriptionRepair(aoSubscription2.getId(), bundleRepair);
             assertEquals(aoRepair2.getExistingEvents().size(), 2);
 
             DateTime bpChangeDate = clock.getUTCNow().minusDays(1);
 
-            List<DeletedEvent> des = new LinkedList<SubscriptionRepair.DeletedEvent>();
+            List<DeletedEvent> des = new LinkedList<SubscriptionTimeline.DeletedEvent>();
             des.add(createDeletedEvent(bpRepair.getExistingEvents().get(1).getEventId()));        
 
             PlanPhaseSpecifier spec = new PlanPhaseSpecifier("Assault-Rifle", ProductCategory.BASE, BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME, PhaseType.TRIAL);
@@ -172,8 +172,8 @@ public class TestRepairIntegration extends TestIntegrationBase {
         }
      }
     
-    protected SubscriptionRepair createSubscriptionReapir(final UUID id, final List<DeletedEvent> deletedEvents, final List<NewEvent> newEvents) {
-        return new SubscriptionRepair() {
+    protected SubscriptionTimeline createSubscriptionReapir(final UUID id, final List<DeletedEvent> deletedEvents, final List<NewEvent> newEvents) {
+        return new SubscriptionTimeline() {
             @Override
             public UUID getId() {
                 return id;
@@ -194,20 +194,24 @@ public class TestRepairIntegration extends TestIntegrationBase {
     }
 
     
-    protected BundleRepair createBundleRepair(final UUID bundleId, final String viewId, final List<SubscriptionRepair> subscriptionRepair) {
-        return new BundleRepair() {
+    protected BundleTimeline createBundleRepair(final UUID bundleId, final String viewId, final List<SubscriptionTimeline> subscriptionRepair) {
+        return new BundleTimeline() {
             @Override
             public String getViewId() {
                 return viewId;
             }
             @Override
-            public List<SubscriptionRepair> getSubscriptions() {
+            public List<SubscriptionTimeline> getSubscriptions() {
                 return subscriptionRepair;
             }
             @Override
             public UUID getBundleId() {
                 return bundleId;
             }
+            @Override
+            public String getExternalKey() {
+                return null;
+            }
         };
     }
 
@@ -241,8 +245,8 @@ public class TestRepairIntegration extends TestIntegrationBase {
         return ev;
     }
     
-    protected SubscriptionRepair getSubscriptionRepair(final UUID id, final BundleRepair bundleRepair) {
-        for (SubscriptionRepair cur : bundleRepair.getSubscriptions()) {
+    protected SubscriptionTimeline getSubscriptionRepair(final UUID id, final BundleTimeline bundleRepair) {
+        for (SubscriptionTimeline cur : bundleRepair.getSubscriptions()) {
             if (cur.getId().equals(id)) {
                 return cur;
             }
@@ -293,11 +297,11 @@ public class TestRepairIntegration extends TestIntegrationBase {
         };
     }
 
-    protected void sortEventsOnBundle(final BundleRepair bundle) {
+    protected void sortEventsOnBundle(final BundleTimeline bundle) {
         if (bundle.getSubscriptions() == null) {
             return;
         }
-        for (SubscriptionRepair cur : bundle.getSubscriptions()) {
+        for (SubscriptionTimeline cur : bundle.getSubscriptions()) {
             if (cur.getExistingEvents() != null) {
                 sortExistingEvent(cur.getExistingEvents());
             }
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/DefaultSubscriptionFactory.java b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/DefaultSubscriptionFactory.java
index 267ace5..eb59d38 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/DefaultSubscriptionFactory.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/DefaultSubscriptionFactory.java
@@ -21,7 +21,7 @@ import com.ning.billing.catalog.api.CatalogService;
 import com.ning.billing.catalog.api.ProductCategory;
 import com.ning.billing.entitlement.api.SubscriptionApiService;
 import com.ning.billing.entitlement.api.SubscriptionFactory;
-import com.ning.billing.entitlement.api.repair.SubscriptionDataRepair;
+import com.ning.billing.entitlement.api.timeline.SubscriptionDataRepair;
 import com.ning.billing.entitlement.events.EntitlementEvent;
 import com.ning.billing.entitlement.exceptions.EntitlementError;
 import com.ning.billing.util.clock.Clock;
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 ac397b6..fd897f6 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
@@ -24,7 +24,7 @@ import com.ning.billing.util.callcontext.CallContext;
 
 import com.ning.billing.entitlement.api.SubscriptionFactory;
 import com.ning.billing.entitlement.api.migration.AccountMigrationData;
-import com.ning.billing.entitlement.api.repair.SubscriptionDataRepair;
+import com.ning.billing.entitlement.api.timeline.SubscriptionDataRepair;
 import com.ning.billing.entitlement.api.user.Subscription;
 import com.ning.billing.entitlement.api.user.SubscriptionBundle;
 import com.ning.billing.entitlement.api.user.SubscriptionBundleData;
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 f216561..efa2e44 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
@@ -54,9 +54,9 @@ import com.ning.billing.entitlement.api.SubscriptionFactory;
 import com.ning.billing.entitlement.api.migration.AccountMigrationData;
 import com.ning.billing.entitlement.api.migration.AccountMigrationData.BundleMigrationData;
 import com.ning.billing.entitlement.api.migration.AccountMigrationData.SubscriptionMigrationData;
-import com.ning.billing.entitlement.api.repair.DefaultRepairEntitlementEvent;
-import com.ning.billing.entitlement.api.repair.RepairEntitlementEvent;
-import com.ning.billing.entitlement.api.repair.SubscriptionDataRepair;
+import com.ning.billing.entitlement.api.timeline.DefaultRepairEntitlementEvent;
+import com.ning.billing.entitlement.api.timeline.RepairEntitlementEvent;
+import com.ning.billing.entitlement.api.timeline.SubscriptionDataRepair;
 import com.ning.billing.entitlement.api.user.Subscription;
 import com.ning.billing.entitlement.api.user.SubscriptionBundle;
 import com.ning.billing.entitlement.api.user.SubscriptionBundleData;
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/RepairEntitlementDao.java b/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/RepairEntitlementDao.java
index 178ea2d..cdfc221 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/RepairEntitlementDao.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/RepairEntitlementDao.java
@@ -27,8 +27,8 @@ import java.util.UUID;
 
 import com.ning.billing.entitlement.api.SubscriptionFactory;
 import com.ning.billing.entitlement.api.migration.AccountMigrationData;
-import com.ning.billing.entitlement.api.repair.RepairEntitlementLifecycleDao;
-import com.ning.billing.entitlement.api.repair.SubscriptionDataRepair;
+import com.ning.billing.entitlement.api.timeline.RepairEntitlementLifecycleDao;
+import com.ning.billing.entitlement.api.timeline.SubscriptionDataRepair;
 import com.ning.billing.entitlement.api.user.Subscription;
 import com.ning.billing.entitlement.api.user.SubscriptionBundle;
 import com.ning.billing.entitlement.api.user.SubscriptionBundleData;
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/glue/EntitlementModule.java b/entitlement/src/main/java/com/ning/billing/entitlement/glue/EntitlementModule.java
index a3810c6..133d278 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/glue/EntitlementModule.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/glue/EntitlementModule.java
@@ -30,11 +30,11 @@ import com.ning.billing.entitlement.api.billing.ChargeThruApi;
 import com.ning.billing.entitlement.api.billing.DefaultChargeThruApi;
 import com.ning.billing.entitlement.api.migration.DefaultEntitlementMigrationApi;
 import com.ning.billing.entitlement.api.migration.EntitlementMigrationApi;
-import com.ning.billing.entitlement.api.repair.DefaultEntitlementRepairApi;
-import com.ning.billing.entitlement.api.repair.EntitlementRepairApi;
-import com.ning.billing.entitlement.api.repair.RepairEntitlementLifecycleDao;
-import com.ning.billing.entitlement.api.repair.RepairSubscriptionApiService;
-import com.ning.billing.entitlement.api.repair.RepairSubscriptionFactory;
+import com.ning.billing.entitlement.api.timeline.DefaultEntitlementTimelineApi;
+import com.ning.billing.entitlement.api.timeline.EntitlementTimelineApi;
+import com.ning.billing.entitlement.api.timeline.RepairEntitlementLifecycleDao;
+import com.ning.billing.entitlement.api.timeline.RepairSubscriptionApiService;
+import com.ning.billing.entitlement.api.timeline.RepairSubscriptionFactory;
 import com.ning.billing.entitlement.api.user.DefaultEntitlementUserApi;
 import com.ning.billing.entitlement.api.user.EntitlementUserApi;
 import com.ning.billing.entitlement.api.user.DefaultSubscriptionApiService;
@@ -75,7 +75,7 @@ public class EntitlementModule extends AbstractModule {
         bind(AddonUtils.class).asEagerSingleton();
         bind(MigrationPlanAligner.class).asEagerSingleton();
         
-        bind(EntitlementRepairApi.class).to(DefaultEntitlementRepairApi.class).asEagerSingleton();
+        bind(EntitlementTimelineApi.class).to(DefaultEntitlementTimelineApi.class).asEagerSingleton();
         bind(EntitlementUserApi.class).to(DefaultEntitlementUserApi.class).asEagerSingleton();
         bind(EntitlementMigrationApi.class).to(DefaultEntitlementMigrationApi.class).asEagerSingleton();
         bind(ChargeThruApi.class).to(DefaultChargeThruApi.class).asEagerSingleton();
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 45455d2..e83cb32 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
@@ -18,7 +18,7 @@ package com.ning.billing.entitlement.api;
 
 import com.google.common.base.Joiner;
 import com.google.common.eventbus.Subscribe;
-import com.ning.billing.entitlement.api.repair.RepairEntitlementEvent;
+import com.ning.billing.entitlement.api.timeline.RepairEntitlementEvent;
 import com.ning.billing.entitlement.api.user.SubscriptionEventTransition;
 import com.ning.billing.util.bus.Bus;
 import org.slf4j.Logger;
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/TestApiBase.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/TestApiBase.java
index 2dfadef..46c707b 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/TestApiBase.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/TestApiBase.java
@@ -56,7 +56,7 @@ import com.ning.billing.dbi.MysqlTestingHelper;
 import com.ning.billing.entitlement.api.ApiTestListener.NextEvent;
 import com.ning.billing.entitlement.api.billing.ChargeThruApi;
 import com.ning.billing.entitlement.api.migration.EntitlementMigrationApi;
-import com.ning.billing.entitlement.api.repair.EntitlementRepairApi;
+import com.ning.billing.entitlement.api.timeline.EntitlementTimelineApi;
 import com.ning.billing.entitlement.api.user.EntitlementUserApi;
 import com.ning.billing.entitlement.api.user.EntitlementUserApiException;
 import com.ning.billing.entitlement.api.user.SubscriptionBundle;
@@ -88,7 +88,7 @@ public abstract class TestApiBase {
     protected ChargeThruApi billingApi;
 
     protected EntitlementMigrationApi migrationApi;
-    protected EntitlementRepairApi repairApi;
+    protected EntitlementTimelineApi repairApi;
 
     protected CatalogService catalogService;
     protected EntitlementConfig config;
@@ -139,7 +139,7 @@ public abstract class TestApiBase {
         entitlementApi = g.getInstance(EntitlementUserApi.class);
         billingApi = g.getInstance(ChargeThruApi.class);
         migrationApi = g.getInstance(EntitlementMigrationApi.class);
-        repairApi = g.getInstance(EntitlementRepairApi.class);
+        repairApi = g.getInstance(EntitlementTimelineApi.class);
         catalogService = g.getInstance(CatalogService.class);
         busService = g.getInstance(BusService.class);
         config = g.getInstance(EntitlementConfig.class);
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 f777204..9b75099 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
@@ -40,7 +40,7 @@ import com.ning.billing.entitlement.api.SubscriptionFactory;
 import com.ning.billing.entitlement.api.migration.AccountMigrationData;
 import com.ning.billing.entitlement.api.migration.AccountMigrationData.BundleMigrationData;
 import com.ning.billing.entitlement.api.migration.AccountMigrationData.SubscriptionMigrationData;
-import com.ning.billing.entitlement.api.repair.SubscriptionDataRepair;
+import com.ning.billing.entitlement.api.timeline.SubscriptionDataRepair;
 import com.ning.billing.entitlement.api.user.Subscription;
 import com.ning.billing.entitlement.api.user.SubscriptionBundle;
 import com.ning.billing.entitlement.api.user.SubscriptionBundleData;
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/glue/MockEngineModuleMemory.java b/entitlement/src/test/java/com/ning/billing/entitlement/glue/MockEngineModuleMemory.java
index 20b91e1..e46e4bc 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/glue/MockEngineModuleMemory.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/glue/MockEngineModuleMemory.java
@@ -18,7 +18,7 @@ package com.ning.billing.entitlement.glue;
 
 
 import com.google.inject.name.Names;
-import com.ning.billing.entitlement.api.repair.RepairEntitlementLifecycleDao;
+import com.ning.billing.entitlement.api.timeline.RepairEntitlementLifecycleDao;
 import com.ning.billing.entitlement.engine.dao.EntitlementDao;
 import com.ning.billing.entitlement.engine.dao.MockEntitlementDaoMemory;
 import com.ning.billing.entitlement.engine.dao.RepairEntitlementDao;
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/glue/MockEngineModuleSql.java b/entitlement/src/test/java/com/ning/billing/entitlement/glue/MockEngineModuleSql.java
index 6d863a9..9195c91 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/glue/MockEngineModuleSql.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/glue/MockEngineModuleSql.java
@@ -26,7 +26,7 @@ import org.skife.jdbi.v2.IDBI;
 import com.ning.billing.dbi.DBIProvider;
 import com.ning.billing.dbi.DbiConfig;
 import com.ning.billing.dbi.MysqlTestingHelper;
-import com.ning.billing.entitlement.api.repair.RepairEntitlementLifecycleDao;
+import com.ning.billing.entitlement.api.timeline.RepairEntitlementLifecycleDao;
 import com.ning.billing.entitlement.engine.dao.EntitlementDao;
 import com.ning.billing.entitlement.engine.dao.MockEntitlementDaoSql;
 
diff --git a/invoice/src/main/java/com/ning/billing/invoice/InvoiceListener.java b/invoice/src/main/java/com/ning/billing/invoice/InvoiceListener.java
index 3a83729..9e4eb08 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/InvoiceListener.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/InvoiceListener.java
@@ -28,7 +28,8 @@ import org.slf4j.LoggerFactory;
 
 import com.google.common.eventbus.Subscribe;
 import com.google.inject.Inject;
-import com.ning.billing.entitlement.api.repair.RepairEntitlementEvent;
+import com.ning.billing.entitlement.api.SubscriptionTransitionType;
+import com.ning.billing.entitlement.api.timeline.RepairEntitlementEvent;
 import com.ning.billing.entitlement.api.user.SubscriptionEventTransition;
 import com.ning.billing.invoice.api.InvoiceApiException;
 
@@ -56,10 +57,13 @@ public class InvoiceListener {
     @Subscribe
     public void handleSubscriptionTransition(final SubscriptionEventTransition transition) {
         try {
-            if (transition.getRemainingEventsForUserOperation() > 0) {
-                // Skip invoice generation as there is more coming...
+            //  Skip future uncancel event
+            //  Skip events which are marked as not being the last one
+            if (transition.getTransitionType() == SubscriptionTransitionType.UNCANCEL 
+                    || transition.getRemainingEventsForUserOperation() > 0) {
                 return;
             }
+
             CallContext context = factory.createCallContext("Transition", CallOrigin.INTERNAL, UserType.SYSTEM, transition.getUserToken());
         	dispatcher.processSubscription(transition, context);
         } catch (InvoiceApiException e) {
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 d81e218..7c5835a 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
@@ -66,10 +66,10 @@ import com.ning.billing.config.InvoiceConfig;
 import com.ning.billing.dbi.MysqlTestingHelper;
 
 import com.ning.billing.entitlement.api.billing.ChargeThruApi;
-import com.ning.billing.entitlement.api.repair.RepairEntitlementLifecycleDao;
-import com.ning.billing.entitlement.api.repair.RepairSubscriptionApiService;
-import com.ning.billing.entitlement.api.repair.RepairSubscriptionFactory;
 
+import com.ning.billing.entitlement.api.timeline.RepairEntitlementLifecycleDao;
+import com.ning.billing.entitlement.api.timeline.RepairSubscriptionApiService;
+import com.ning.billing.entitlement.api.timeline.RepairSubscriptionFactory;
 import com.ning.billing.entitlement.api.user.DefaultEntitlementUserApi;
 import com.ning.billing.entitlement.api.user.DefaultSubscriptionApiService;
 import com.ning.billing.entitlement.api.user.DefaultSubscriptionFactory;
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/AccountJson.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/AccountJson.java
index 13ad140..4401b06 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/AccountJson.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/AccountJson.java
@@ -18,38 +18,61 @@ package com.ning.billing.jaxrs.json;
 
 import org.codehaus.jackson.annotate.JsonCreator;
 import org.codehaus.jackson.annotate.JsonProperty;
+import org.codehaus.jackson.map.annotate.JsonView;
 import org.joda.time.DateTimeZone;
 
 import com.ning.billing.account.api.Account;
 import com.ning.billing.account.api.AccountData;
 import com.ning.billing.catalog.api.Currency;
 
-public class AccountJson {
+public class AccountJson extends AccountJsonSimple {
 
-    // Missing city, locale, postalCode from https://home.ninginc.com:8443/display/REVINFRA/Killbill+1.0+APIs
+    // STEPH Missing city, locale, postalCode from https://home.ninginc.com:8443/display/REVINFRA/Killbill+1.0+APIs
 
-    private final String acountId;
+    @JsonView(BundleTimelineViews.Base.class)
     private final String name;
+    
+    @JsonView(BundleTimelineViews.Base.class)
     private final Integer length;
-    private final String externalKey;
+        
+    @JsonView(BundleTimelineViews.Base.class)
     private final String email;
+    
+    @JsonView(BundleTimelineViews.Base.class)
     private final Integer billCycleDay;
+    
+    @JsonView(BundleTimelineViews.Base.class)
     private final String currency;
+    
+    @JsonView(BundleTimelineViews.Base.class)
     private final String paymentProvider;
+    
+    @JsonView(BundleTimelineViews.Base.class)
     private final String timeZone;
+    
+    @JsonView(BundleTimelineViews.Base.class)
     private final String address1;
+    
+    @JsonView(BundleTimelineViews.Base.class)
     private final String address2;
+    
+    @JsonView(BundleTimelineViews.Base.class)
     private final String company;
+    
+    @JsonView(BundleTimelineViews.Base.class)
     private final String state;
+    
+    @JsonView(BundleTimelineViews.Base.class)
     private final String country;
+    
+    @JsonView(BundleTimelineViews.Base.class)
     private final String phone;
 
 
     public AccountJson(Account account) {
-        this.acountId = account.getId().toString();
+        super(account.getId().toString(), account.getExternalKey());
         this.name = account.getName();
         this.length = account.getFirstNameLength();
-        this.externalKey = account.getExternalKey();
         this.email = account.getEmail();
         this.billCycleDay = account.getBillCycleDay();
         this.currency = account.getCurrency().toString();
@@ -140,10 +163,9 @@ public class AccountJson {
     // Seems like Jackson (JacksonJsonProvider.readFrom(Class<Object>, Type, Annotation[], MediaType, MultivaluedMap<String,String>, InputStream) line: 443)
     // needs us to define a default CTOR to instanciate the class first.
     public AccountJson() {
-        this.acountId = null;
+        super();
         this.name = null;
         this.length = null;
-        this.externalKey = null;
         this.email = null;
         this.billCycleDay = null;
         this.currency = null;
@@ -173,11 +195,9 @@ public class AccountJson {
             @JsonProperty("state") String state,
             @JsonProperty("country") String country,
             @JsonProperty("phone") String phone) {
-        super();
-        this.acountId = acountId;
+        super(acountId, externalKey);
         this.name = name;
         this.length = length;
-        this.externalKey = externalKey;
         this.email = email;
         this.billCycleDay = billCycleDay;
         this.currency = currency;
@@ -191,10 +211,6 @@ public class AccountJson {
         this.phone = phone;
     }
 
-    public String getAcountId() {
-        return acountId;
-    }
-
     public String getName() {
         return name;
     }
@@ -203,10 +219,6 @@ public class AccountJson {
         return length;
     }
 
-    public String getExternalKey() {
-        return externalKey;
-    }
-
     public String getEmail() {
         return email;
     }
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/AccountJsonSimple.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/AccountJsonSimple.java
new file mode 100644
index 0000000..548635e
--- /dev/null
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/AccountJsonSimple.java
@@ -0,0 +1,49 @@
+/* 
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+package com.ning.billing.jaxrs.json;
+
+import org.codehaus.jackson.annotate.JsonCreator;
+import org.codehaus.jackson.annotate.JsonProperty;
+import org.codehaus.jackson.map.annotate.JsonView;
+
+public class AccountJsonSimple {
+
+    @JsonView(BundleTimelineViews.Base.class)
+    protected final String acountId;
+    
+    @JsonView(BundleTimelineViews.Base.class)
+    protected final String externalKey;
+    
+    public AccountJsonSimple() {
+        this.acountId = null;
+        this.externalKey = null;
+    }
+
+    @JsonCreator
+    public AccountJsonSimple(@JsonProperty("account_id") String acountId,
+            @JsonProperty("external_key") String externalKey) {
+        this.acountId = acountId;
+        this.externalKey = externalKey;
+    }
+
+    public String getAcountId() {
+        return acountId;
+    }
+
+    public String getExternalKey() {
+        return externalKey;
+    }
+}
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/AccountTimelineJson.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/AccountTimelineJson.java
new file mode 100644
index 0000000..1241b7d
--- /dev/null
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/AccountTimelineJson.java
@@ -0,0 +1,94 @@
+/* 
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+package com.ning.billing.jaxrs.json;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import org.codehaus.jackson.annotate.JsonCreator;
+import org.codehaus.jackson.annotate.JsonProperty;
+import org.codehaus.jackson.map.annotate.JsonView;
+
+import com.ning.billing.account.api.Account;
+import com.ning.billing.entitlement.api.timeline.BundleTimeline;
+import com.ning.billing.invoice.api.Invoice;
+import com.ning.billing.payment.api.PaymentInfoEvent;
+
+public class AccountTimelineJson {
+
+    @JsonView(BundleTimelineViews.ReadTimeline.class)
+    private final List<PaymentJson> payments;
+
+    @JsonView(BundleTimelineViews.ReadTimeline.class)
+    private final List<InvoiceJson> invoices;
+    
+    @JsonView(BundleTimelineViews.ReadTimeline.class)
+    private final AccountJsonSimple account;
+    
+    @JsonView(BundleTimelineViews.Timeline.class)
+    private final List<BundleJsonWithSubscriptions> bundles;
+    
+    @JsonCreator
+    public AccountTimelineJson(@JsonProperty("account") AccountJsonSimple account,
+            @JsonProperty("bundles") List<BundleJsonWithSubscriptions> bundles,
+            @JsonProperty("invoices") List<InvoiceJson> invoices,            
+            @JsonProperty("payments") List<PaymentJson> payments) {
+        this.account = account;
+        this.bundles = bundles;
+        this.invoices = invoices;
+        this.payments = payments;
+    }
+    
+    public AccountTimelineJson(Account account, List<Invoice> invoices, List<PaymentInfoEvent> payments, List<BundleTimeline> bundles) {
+        this.account = new AccountJsonSimple(account.getId().toString(), account.getExternalKey());
+        this.bundles = new LinkedList<BundleJsonWithSubscriptions>();
+        for (BundleTimeline cur : bundles) {
+            this.bundles.add(new BundleJsonWithSubscriptions(account.getId(), cur));            
+        }
+        this.invoices = new LinkedList<InvoiceJson>();
+        for (Invoice cur : invoices) {
+            this.invoices.add(new InvoiceJson(cur.getTotalAmount(), cur.getId().toString(), cur.getInvoiceDate(), Integer.toString(cur.getInvoiceNumber()), cur.getBalance()));
+        }
+        this.payments = new LinkedList<PaymentJson>();
+        for (PaymentInfoEvent cur : payments) {
+            // STEPH how to link that payment with the invoice ??
+            this.payments.add(new PaymentJson(cur.getAmount(), null , cur.getPaymentNumber(), null, cur.getEffectiveDate(), cur.getStatus()));
+        }
+    }
+    
+    public AccountTimelineJson() {
+        this.account = null;
+        this.bundles = null;
+        this.invoices = null;
+        this.payments = null;
+    }
+
+    public List<PaymentJson> getPayments() {
+        return payments;
+    }
+
+    public List<InvoiceJson> getInvoices() {
+        return invoices;
+    }
+
+    public AccountJsonSimple getAccount() {
+        return account;
+    }
+
+    public List<BundleJsonWithSubscriptions> getBundles() {
+        return bundles;
+    }
+}
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/BundleJsonSimple.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/BundleJsonSimple.java
new file mode 100644
index 0000000..3053f0d
--- /dev/null
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/BundleJsonSimple.java
@@ -0,0 +1,48 @@
+/* 
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+package com.ning.billing.jaxrs.json;
+
+import org.codehaus.jackson.annotate.JsonCreator;
+import org.codehaus.jackson.map.annotate.JsonView;
+
+public class BundleJsonSimple {
+    
+    @JsonView(BundleTimelineViews.Base.class)
+    protected final String bundleId;
+
+    @JsonView(BundleTimelineViews.Base.class)
+    protected final String externalKey;
+
+    @JsonCreator
+    public BundleJsonSimple(String bundleId, String externalKey) {
+        super();
+        this.bundleId = bundleId;
+        this.externalKey = externalKey;
+    }
+    
+    public BundleJsonSimple() {
+        this.bundleId = null;
+        this.externalKey = null;
+    }
+
+    public String getBundleId() {
+        return bundleId;
+    }
+
+    public String getExternalKey() {
+        return externalKey;
+    }
+}
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/BundleJsonWithSubscriptions.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/BundleJsonWithSubscriptions.java
new file mode 100644
index 0000000..dd2c788
--- /dev/null
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/BundleJsonWithSubscriptions.java
@@ -0,0 +1,65 @@
+/* 
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+package com.ning.billing.jaxrs.json;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.UUID;
+
+import org.codehaus.jackson.annotate.JsonCreator;
+import org.codehaus.jackson.annotate.JsonProperty;
+import org.codehaus.jackson.map.annotate.JsonView;
+
+import com.ning.billing.entitlement.api.timeline.BundleTimeline;
+import com.ning.billing.entitlement.api.timeline.SubscriptionTimeline;
+import com.ning.billing.entitlement.api.user.SubscriptionBundle;
+
+public class BundleJsonWithSubscriptions extends BundleJsonSimple {
+
+    @JsonView(BundleTimelineViews.Timeline.class)
+    private final List<SubscriptionJsonWithEvents> subscriptions;
+
+    @JsonCreator
+    public BundleJsonWithSubscriptions(@JsonProperty("bundle_id") String bundleId,
+            @JsonProperty("external_key") String externalKey,
+            @JsonProperty("subscriptions") List<SubscriptionJsonWithEvents> subscriptions) {
+        super(bundleId, externalKey);
+        this.subscriptions = subscriptions;
+    }
+
+    public List<SubscriptionJsonWithEvents> getSubscriptions() {
+        return subscriptions;
+    }
+
+    public BundleJsonWithSubscriptions(final UUID accountId, final BundleTimeline bundle) {
+        super(bundle.getBundleId().toString(), bundle.getExternalKey());
+        this.subscriptions = new LinkedList<SubscriptionJsonWithEvents>();
+        for (SubscriptionTimeline cur : bundle.getSubscriptions()) {
+            this.subscriptions.add(new SubscriptionJsonWithEvents(bundle.getBundleId(), cur)); 
+        }
+    }
+    
+    public BundleJsonWithSubscriptions(SubscriptionBundle bundle) {
+        super(bundle.getId().toString(), bundle.getKey());        
+        this.subscriptions = null;
+    }
+    
+    public BundleJsonWithSubscriptions() {
+        super(null, null);        
+        this.subscriptions = null;
+    }
+
+}
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/BundleTimelineJson.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/BundleTimelineJson.java
index 61761a7..64a416c 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/BundleTimelineJson.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/BundleTimelineJson.java
@@ -28,7 +28,7 @@ public class BundleTimelineJson {
     private final String viewId;
 
     @JsonView(BundleTimelineViews.Timeline.class)
-    private final BundleJson bundle;
+    private final BundleJsonWithSubscriptions bundle;
 
     @JsonView(BundleTimelineViews.ReadTimeline.class)
     private final List<PaymentJson> payments;
@@ -41,7 +41,7 @@ public class BundleTimelineJson {
 
     @JsonCreator
     public BundleTimelineJson(@JsonProperty("view_id") String viewId,
-            @JsonProperty("bundle") BundleJson bundle,
+            @JsonProperty("bundle") BundleJsonWithSubscriptions bundle,
             @JsonProperty("payments") List<PaymentJson> payments,
             @JsonProperty("invoices") List<InvoiceJson> invoices,
             @JsonProperty("reason_for_change") String reason) {
@@ -56,7 +56,7 @@ public class BundleTimelineJson {
         return viewId;
     }
 
-    public BundleJson getBundle() {
+    public BundleJsonWithSubscriptions getBundle() {
         return bundle;
     }
 
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/BundleTimelineViews.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/BundleTimelineViews.java
index 020764e..0397bec 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/BundleTimelineViews.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/BundleTimelineViews.java
@@ -18,8 +18,8 @@ package com.ning.billing.jaxrs.json;
 
 
 public class BundleTimelineViews {
-    static class Base {};
-    static class Timeline extends Base {};
-    static class ReadTimeline extends Timeline {};
-    static class WriteTimeline extends Timeline {};
+    public static class Base {};
+    public static class Timeline extends Base {};
+    public static class ReadTimeline extends Timeline {};
+    public static class WriteTimeline extends Timeline {};
 }
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/InvoiceJson.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/InvoiceJson.java
index b13bdee..30264d7 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/InvoiceJson.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/InvoiceJson.java
@@ -20,26 +20,36 @@ import java.math.BigDecimal;
 
 import org.codehaus.jackson.annotate.JsonCreator;
 import org.codehaus.jackson.annotate.JsonProperty;
+import org.codehaus.jackson.map.annotate.JsonView;
 import org.joda.time.DateTime;
 
 public class InvoiceJson {
 
+    @JsonView(BundleTimelineViews.Base.class)
     private final BigDecimal amount;
+    
+    @JsonView(BundleTimelineViews.Base.class)
     private final String invoiceId;
-    private final DateTime requestedDate;
+    
+    @JsonView(BundleTimelineViews.Base.class)
+    private final DateTime invoiceDate;
+    
+    @JsonView(BundleTimelineViews.Base.class)
     private final String invoiceNumber;
+    
+    @JsonView(BundleTimelineViews.Base.class)
     private final BigDecimal balance;
 
     @JsonCreator
     public InvoiceJson(@JsonProperty("amount") BigDecimal amount,
             @JsonProperty("invoice_id") String invoiceId,
-            @JsonProperty("requested_dt") DateTime requestedDate,
+            @JsonProperty("invoice_date") DateTime invoiceDate,
             @JsonProperty("invoice_number") String invoiceNumber,
             @JsonProperty("balance") BigDecimal balance) {
         super();
         this.amount = amount;
         this.invoiceId = invoiceId;
-        this.requestedDate = requestedDate;
+        this.invoiceDate = invoiceDate;
         this.invoiceNumber = invoiceNumber;
         this.balance = balance;
     }
@@ -52,8 +62,8 @@ public class InvoiceJson {
         return invoiceId;
     }
 
-    public DateTime getRequestedDate() {
-        return requestedDate;
+    public DateTime getInvoiceDate() {
+        return invoiceDate;
     }
 
     public String getInvoiceNumber() {
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/PaymentJson.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/PaymentJson.java
index 1f932d4..3a9fd4d 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/PaymentJson.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/PaymentJson.java
@@ -20,17 +20,29 @@ import java.math.BigDecimal;
 
 import org.codehaus.jackson.annotate.JsonCreator;
 import org.codehaus.jackson.annotate.JsonProperty;
+import org.codehaus.jackson.map.annotate.JsonView;
 import org.joda.time.DateTime;
 
 import com.ning.billing.util.clock.DefaultClock;
 
 public class PaymentJson {
 
+    @JsonView(BundleTimelineViews.Base.class)
     private final BigDecimal paidAmount;
+    
+    @JsonView(BundleTimelineViews.Base.class)
     private final String invoiceId;
+    
+    @JsonView(BundleTimelineViews.Base.class)
     private final String paymentId;
+    
+    @JsonView(BundleTimelineViews.Base.class)
     private final DateTime requestedDate;
+    
+    @JsonView(BundleTimelineViews.Base.class)
     private final DateTime effectiveDate;
+    
+    @JsonView(BundleTimelineViews.Base.class)
     private final String status;
 
     @JsonCreator
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/SubscriptionJsonNoEvents.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/SubscriptionJsonNoEvents.java
new file mode 100644
index 0000000..2ec1c44
--- /dev/null
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/SubscriptionJsonNoEvents.java
@@ -0,0 +1,210 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.jaxrs.json;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.UUID;
+
+import org.codehaus.jackson.annotate.JsonCreator;
+import org.codehaus.jackson.annotate.JsonProperty;
+import org.codehaus.jackson.map.annotate.JsonView;
+import org.joda.time.DateTime;
+
+import com.ning.billing.catalog.api.PlanPhaseSpecifier;
+import com.ning.billing.entitlement.api.timeline.SubscriptionTimeline;
+import com.ning.billing.entitlement.api.timeline.SubscriptionTimeline.ExistingEvent;
+import com.ning.billing.entitlement.api.user.Subscription;
+import com.ning.billing.util.clock.DefaultClock;
+
+public class SubscriptionJsonNoEvents extends SubscriptionJsonSimple {
+
+    @JsonView(BundleTimelineViews.Base.class)
+    private final DateTime startDate;
+    
+    @JsonView(BundleTimelineViews.Base.class)
+    private final String bundleId;
+
+    @JsonView(BundleTimelineViews.Base.class)
+    private final String productName;
+
+    @JsonView(BundleTimelineViews.Base.class)
+    private final String productCategory;
+
+    @JsonView(BundleTimelineViews.Base.class)
+    private final String billingPeriod;
+
+    @JsonView(BundleTimelineViews.Base.class)
+    private final String priceList;
+
+    @JsonView(BundleTimelineViews.Base.class)
+    private final DateTime chargedThroughDate;
+    
+
+
+    @JsonCreator
+    public SubscriptionJsonNoEvents(@JsonProperty("subscription_id") String subscriptionId,
+            @JsonProperty("bundle_id") String bundleId,
+            @JsonProperty("start_date") DateTime startDate,
+            @JsonProperty("product_name") String productName,
+            @JsonProperty("product_category") String productCategory,
+            @JsonProperty("billing_period") String billingPeriod,
+            @JsonProperty("price_list") String priceList,
+            @JsonProperty("charged_through_date") DateTime chargedThroughDate) {
+        super(subscriptionId);
+        this.bundleId = bundleId;
+        this.startDate = startDate;
+        this.productName = productName;
+        this.productCategory = productCategory;
+        this.billingPeriod = billingPeriod;
+        this.priceList = priceList;
+        this.chargedThroughDate = chargedThroughDate;
+    }
+    
+    public SubscriptionJsonNoEvents() {
+        super(null);
+        this.bundleId = null;
+        this.startDate = null;
+        this.productName = null;
+        this.productCategory = null;
+        this.billingPeriod = null;
+        this.priceList = null;
+        this.chargedThroughDate = null;        
+    }
+    
+    public SubscriptionJsonNoEvents(final Subscription data) {
+        super(data.getId().toString());
+        this.bundleId = data.getBundleId().toString();
+        this.startDate = data.getStartDate();
+        this.productName = data.getCurrentPlan().getProduct().getName();
+        this.productCategory = data.getCurrentPlan().getProduct().getCategory().toString();
+        this.billingPeriod = data.getCurrentPlan().getBillingPeriod().toString();
+        this.priceList = data.getCurrentPriceList().getName();
+        this.chargedThroughDate = data.getChargedThroughDate();
+    }
+   
+
+    public String getSubscriptionId() {
+        return subscriptionId;
+    }
+
+    public String getBundleId() {
+        return bundleId;
+    }
+    
+    public DateTime getStartDate() {
+        return startDate;
+    }
+
+    public String getProductName() {
+        return productName;
+    }
+
+    public String getProductCategory() {
+        return productCategory;
+    }
+
+    public String getBillingPeriod() {
+        return billingPeriod;
+    }
+
+    public String getPriceList() {
+        return priceList;
+    }
+    
+    public DateTime getChargedThroughDate() {
+        return chargedThroughDate;
+    }
+
+
+    @Override
+    public String toString() {
+        return "SubscriptionJson [subscriptionId=" + subscriptionId
+                + ", bundleId=" + bundleId + ", productName=" + productName
+                + ", productCategory=" + productCategory + ", billingPeriod="
+                + billingPeriod + ", priceList=" + priceList + "]";
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result
+                + ((billingPeriod == null) ? 0 : billingPeriod.hashCode());
+        result = prime * result
+                + ((bundleId == null) ? 0 : bundleId.hashCode());
+        result = prime * result
+                + ((priceList == null) ? 0 : priceList.hashCode());
+        result = prime * result
+                + ((productCategory == null) ? 0 : productCategory.hashCode());
+        result = prime * result
+                + ((productName == null) ? 0 : productName.hashCode());
+        result = prime * result
+                + ((subscriptionId == null) ? 0 : subscriptionId.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (equalsNoId(obj) == false) {
+            return false;
+        }
+        SubscriptionJsonNoEvents other = (SubscriptionJsonNoEvents) obj;
+        if (subscriptionId == null) {
+            if (other.subscriptionId != null)
+                return false;
+        } else if (!subscriptionId.equals(other.subscriptionId))
+            return false;
+        return true;
+    }
+
+    public boolean equalsNoId(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        SubscriptionJsonNoEvents other = (SubscriptionJsonNoEvents) obj;
+        if (billingPeriod == null) {
+            if (other.billingPeriod != null)
+                return false;
+        } else if (!billingPeriod.equals(other.billingPeriod))
+            return false;
+        if (bundleId == null) {
+            if (other.bundleId != null)
+                return false;
+        } else if (!bundleId.equals(other.bundleId))
+            return false;
+        if (priceList == null) {
+            if (other.priceList != null)
+                return false;
+        } else if (!priceList.equals(other.priceList))
+            return false;
+        if (productCategory == null) {
+            if (other.productCategory != null)
+                return false;
+        } else if (!productCategory.equals(other.productCategory))
+            return false;
+        if (productName == null) {
+            if (other.productName != null)
+                return false;
+        } else if (!productName.equals(other.productName))
+            return false;
+        return true;
+    }
+}
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/SubscriptionJsonSimple.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/SubscriptionJsonSimple.java
new file mode 100644
index 0000000..ebb86e4
--- /dev/null
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/SubscriptionJsonSimple.java
@@ -0,0 +1,39 @@
+/* 
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+package com.ning.billing.jaxrs.json;
+
+import org.codehaus.jackson.annotate.JsonCreator;
+import org.codehaus.jackson.annotate.JsonProperty;
+import org.codehaus.jackson.map.annotate.JsonView;
+
+public class SubscriptionJsonSimple {
+    
+    @JsonView(BundleTimelineViews.Base.class)
+    protected final String subscriptionId;
+
+    public SubscriptionJsonSimple() {
+        this.subscriptionId = null;
+    }
+
+    @JsonCreator
+    public SubscriptionJsonSimple(@JsonProperty("subscription_id") String subscriptionId) {
+        this.subscriptionId = subscriptionId;
+    }
+
+    public String getSubscriptionId() {
+        return subscriptionId;
+    }
+}
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/AccountResource.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/AccountResource.java
index 49203f5..13a267e 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/AccountResource.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/AccountResource.java
@@ -19,7 +19,10 @@ package com.ning.billing.jaxrs.resources;
 import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
 
 import java.net.URI;
+import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.UUID;
 
@@ -48,12 +51,20 @@ import com.ning.billing.account.api.Account;
 import com.ning.billing.account.api.AccountApiException;
 import com.ning.billing.account.api.AccountData;
 import com.ning.billing.account.api.AccountUserApi;
+import com.ning.billing.entitlement.api.timeline.BundleTimeline;
+import com.ning.billing.entitlement.api.timeline.EntitlementRepairException;
+import com.ning.billing.entitlement.api.timeline.EntitlementTimelineApi;
 import com.ning.billing.entitlement.api.user.EntitlementUserApi;
 import com.ning.billing.entitlement.api.user.SubscriptionBundle;
+import com.ning.billing.invoice.api.Invoice;
+import com.ning.billing.invoice.api.InvoiceUserApi;
 import com.ning.billing.jaxrs.json.AccountJson;
-import com.ning.billing.jaxrs.json.BundleJson;
+import com.ning.billing.jaxrs.json.AccountTimelineJson;
+import com.ning.billing.jaxrs.json.BundleJsonNoSubsciptions;
 import com.ning.billing.jaxrs.util.Context;
 import com.ning.billing.jaxrs.util.JaxrsUriBuilder;
+import com.ning.billing.payment.api.PaymentApi;
+import com.ning.billing.payment.api.PaymentInfoEvent;
 
 
 @Singleton
@@ -64,14 +75,26 @@ public class AccountResource implements BaseJaxrsResource {
 
     private final AccountUserApi accountApi;
     private final EntitlementUserApi entitlementApi;
+    private final EntitlementTimelineApi timelineApi;
+    private final InvoiceUserApi invoiceApi;
+    private final PaymentApi paymentApi;
     private final Context context;
     private final JaxrsUriBuilder uriBuilder;
 
     @Inject
-    public AccountResource(final JaxrsUriBuilder uriBuilder, final AccountUserApi accountApi, final EntitlementUserApi entitlementApi, final Context context) {
+    public AccountResource(final JaxrsUriBuilder uriBuilder,
+            final AccountUserApi accountApi,
+            final EntitlementUserApi entitlementApi, 
+            final InvoiceUserApi invoiceApi,
+            final PaymentApi paymentApi,
+            final EntitlementTimelineApi timelineApi,
+            final Context context) {
         this.uriBuilder = uriBuilder;
     	this.accountApi = accountApi;
         this.entitlementApi = entitlementApi;
+        this.invoiceApi = invoiceApi;
+        this.paymentApi = paymentApi;
+        this.timelineApi = timelineApi;
         this.context = context;
     }
 
@@ -81,7 +104,7 @@ public class AccountResource implements BaseJaxrsResource {
     public Response getAccount(@PathParam("accountId") String accountId) {
         Account account = accountApi.getAccountById(UUID.fromString(accountId));
         if (account == null) {
-        	return Response.status(Status.NO_CONTENT).build();
+            return Response.status(Status.NO_CONTENT).build();
         }
         AccountJson json = new AccountJson(account);
         return Response.status(Status.OK).entity(json).build();
@@ -98,10 +121,10 @@ public class AccountResource implements BaseJaxrsResource {
     		return Response.status(Status.NO_CONTENT).build();    		
     	}
     	List<SubscriptionBundle> bundles = entitlementApi.getBundlesForAccount(uuid);
-    	Collection<BundleJson> result = Collections2.transform(bundles, new Function<SubscriptionBundle, BundleJson>() {
+    	Collection<BundleJsonNoSubsciptions> result = Collections2.transform(bundles, new Function<SubscriptionBundle, BundleJsonNoSubsciptions>() {
 			@Override
-			public BundleJson apply(SubscriptionBundle input) {
-				return new BundleJson(input);
+			public BundleJsonNoSubsciptions apply(SubscriptionBundle input) {
+				return new BundleJsonNoSubsciptions(input);
 			}
 		});
         return Response.status(Status.OK).entity(result).build();
@@ -176,4 +199,43 @@ public class AccountResource implements BaseJaxrsResource {
        */
         return Response.status(Status.INTERNAL_SERVER_ERROR).build();
     }
+
+    @GET
+    @Path("/{accountId:" + UUID_PATTERN + "}/" + TIMELINE)
+    @Produces(APPLICATION_JSON)
+    public Response getAccountTimeline(@PathParam("accountId") String accountId) {
+        try {
+            Account account = accountApi.getAccountById(UUID.fromString(accountId));
+            if (account == null) {
+                return Response.status(Status.NO_CONTENT).build();
+            }
+
+            List<Invoice> invoices = invoiceApi.getInvoicesByAccount(account.getId());
+            List<PaymentInfoEvent> payments = Collections.emptyList();
+
+            if (invoices.size() > 0) {
+                Collection<String> tmp = Collections2.transform(invoices, new Function<Invoice, String>() {
+                    @Override
+                    public String apply(Invoice input) {
+                        return input.getId().toString();
+                    }
+                });
+                List<String> invoicesId = new ArrayList<String>();
+                invoicesId.addAll(tmp);
+
+                payments = paymentApi.getPaymentInfo(invoicesId);
+            }
+
+            List<SubscriptionBundle> bundles = entitlementApi.getBundlesForAccount(account.getId());
+            List<BundleTimeline> bundlesTimeline = new LinkedList<BundleTimeline>();
+            for (SubscriptionBundle cur : bundles) {
+                bundlesTimeline.add(timelineApi.getBundleRepair(cur.getId()));
+            }
+            AccountTimelineJson json = new AccountTimelineJson(account, invoices, payments, bundlesTimeline);
+            return Response.status(Status.OK).entity(json).build();
+        } catch (EntitlementRepairException e) {
+            log.error(e.getMessage());
+            return Response.status(Status.INTERNAL_SERVER_ERROR).build();
+        }
+    }
 }
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/BaseJaxrsResource.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/BaseJaxrsResource.java
index 3fb0334..79f4b04 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/BaseJaxrsResource.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/BaseJaxrsResource.java
@@ -20,6 +20,8 @@ public interface BaseJaxrsResource {
 	public static final String API_PREFIX = "";
 	public static final String API_VERSION = "/1.0";
 	
+	public static final String TIMELINE = "timeline";
+	
 	/*
 	 * Patterns
 	 */
@@ -35,7 +37,7 @@ public interface BaseJaxrsResource {
 	
 	public static final String ACCOUNTS = "accounts";	
 	public static final String ACCOUNTS_PATH = API_PREFIX + API_VERSION + "/" + ACCOUNTS;
-	
+
 	public static final String BUNDLES = "bundles";		
 	public static final String BUNDLES_PATH = API_PREFIX + API_VERSION + "/" + BUNDLES;
 
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/BundleResource.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/BundleResource.java
index d6a94ab..ef3367e 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/BundleResource.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/BundleResource.java
@@ -42,8 +42,8 @@ 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.jaxrs.json.BundleJson;
-import com.ning.billing.jaxrs.json.SubscriptionJson;
+import com.ning.billing.jaxrs.json.BundleJsonNoSubsciptions;
+import com.ning.billing.jaxrs.json.SubscriptionJsonNoEvents;
 import com.ning.billing.jaxrs.util.Context;
 import com.ning.billing.jaxrs.util.JaxrsUriBuilder;
 
@@ -71,7 +71,7 @@ public class BundleResource implements BaseJaxrsResource {
 		if (bundle == null) {
 			return Response.status(Status.NO_CONTENT).build();
 		}
-		BundleJson json = new BundleJson(bundle);
+		BundleJsonNoSubsciptions json = new BundleJsonNoSubsciptions(bundle);
 		return Response.status(Status.OK).entity(json).build();
 	}
 
@@ -82,14 +82,14 @@ public class BundleResource implements BaseJaxrsResource {
 		if (bundle == null) {
 			return Response.status(Status.NO_CONTENT).build();
 		}
-		BundleJson json = new BundleJson(bundle);
+		BundleJsonNoSubsciptions json = new BundleJsonNoSubsciptions(bundle);
 		return Response.status(Status.OK).entity(json).build();
 	}
 
 	@POST
 	@Consumes(APPLICATION_JSON)
 	@Produces(APPLICATION_JSON)
-	public Response createBundle(final BundleJson json) {
+	public Response createBundle(final BundleJsonNoSubsciptions json) {
 		try {
 			UUID accountId = UUID.fromString(json.getAccountId());
 			final SubscriptionBundle bundle = entitlementApi.createBundleForAccount(accountId, json.getExternalKey(), context.createContext());
@@ -111,10 +111,10 @@ public class BundleResource implements BaseJaxrsResource {
 			return Response.status(Status.NO_CONTENT).build();
 		}
 		List<Subscription> bundles = entitlementApi.getSubscriptionsForBundle(uuid);
-		Collection<SubscriptionJson> result =  Collections2.transform(bundles, new Function<Subscription, SubscriptionJson>() {
+		Collection<SubscriptionJsonNoEvents> result =  Collections2.transform(bundles, new Function<Subscription, SubscriptionJsonNoEvents>() {
 			@Override
-			public SubscriptionJson apply(Subscription input) {
-				return new SubscriptionJson(input, null, null, null);
+			public SubscriptionJsonNoEvents apply(Subscription input) {
+				return new SubscriptionJsonNoEvents(input);
 			}
 		});
 		return Response.status(Status.OK).entity(result).build();
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 8c5c5bd..68ea35f 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
@@ -18,6 +18,10 @@ package com.ning.billing.jaxrs.resources;
 
 import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
 
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.StringWriter;
+import java.io.Writer;
 import java.math.BigDecimal;
 import java.util.UUID;
 import java.util.concurrent.TimeoutException;
@@ -33,9 +37,15 @@ import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
 import javax.ws.rs.Produces;
 import javax.ws.rs.QueryParam;
+import javax.ws.rs.WebApplicationException;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.Response.Status;
+import javax.ws.rs.core.StreamingOutput;
 
+import org.codehaus.jackson.JsonGenerator;
+import org.codehaus.jackson.map.ObjectMapper;
+import org.codehaus.jackson.map.ObjectWriter;
+import org.codehaus.jackson.map.SerializationConfig;
 import org.joda.time.DateTime;
 import org.joda.time.format.DateTimeFormatter;
 import org.joda.time.format.ISODateTimeFormat;
@@ -52,7 +62,8 @@ import com.ning.billing.entitlement.api.user.Subscription;
 import com.ning.billing.entitlement.api.user.SubscriptionEventTransition;
 import com.ning.billing.invoice.api.EmptyInvoiceEvent;
 import com.ning.billing.invoice.api.InvoiceCreationEvent;
-import com.ning.billing.jaxrs.json.SubscriptionJson;
+import com.ning.billing.jaxrs.json.BundleTimelineViews;
+import com.ning.billing.jaxrs.json.SubscriptionJsonNoEvents;
 import com.ning.billing.jaxrs.util.Context;
 import com.ning.billing.jaxrs.util.JaxrsUriBuilder;
 import com.ning.billing.jaxrs.util.KillbillEventHandler;
@@ -63,7 +74,7 @@ import com.ning.billing.util.clock.Clock;
 import com.ning.billing.util.userrequest.CompletionUserRequestBase;
 
 @Path(BaseJaxrsResource.SUBSCRIPTIONS_PATH)
-public class SubscriptionResource implements BaseJaxrsResource{
+public class SubscriptionResource implements BaseJaxrsResource {
 
     private static final Logger log = LoggerFactory.getLogger(SubscriptionResource.class);
 
@@ -73,7 +84,9 @@ public class SubscriptionResource implements BaseJaxrsResource{
     private final Context context;
     private final JaxrsUriBuilder uriBuilder;	
     private final KillbillEventHandler killbillHandler;
+    
 
+    
     @Inject
     public SubscriptionResource(final JaxrsUriBuilder uriBuilder, final EntitlementUserApi entitlementApi,
             final Clock clock, final Context context, final KillbillEventHandler killbillHandler) {
@@ -94,14 +107,47 @@ public class SubscriptionResource implements BaseJaxrsResource{
         if (subscription == null) {
             return Response.status(Status.NO_CONTENT).build();
         }
-        SubscriptionJson json = new SubscriptionJson(subscription, null, null, null);
+        SubscriptionJsonNoEvents json = new SubscriptionJsonNoEvents(subscription);
         return Response.status(Status.OK).entity(json).build();
     }
+    
+    /*
+    @GET
+    @Path("/{subscriptionId:" + UUID_PATTERN + "}")
+    @Produces(APPLICATION_JSON)
+    public StreamingOutput getSubscription(@PathParam("subscriptionId") final String subscriptionId) {
+
+        UUID uuid = UUID.fromString(subscriptionId);
+        final Subscription subscription = entitlementApi.getSubscriptionFromId(uuid);
+        if (subscription == null) {
+            throw new WebApplicationException(Response.Status.NO_CONTENT);
+        }
+        final SubscriptionJson json = new SubscriptionJson(subscription, null, null, null);
+        return new StreamingOutput() {
+
+            final SubscriptionJson json = new SubscriptionJson(subscription, null, null, null);
+            
+            @Override
+            public void write(OutputStream output) throws IOException,
+                    WebApplicationException {
+                
+                final ObjectWriter objWriter = objectMapper.writerWithView(BundleTimelineViews.Base.class);
+                
+                Writer writer = new StringWriter();
+                objWriter.writeValue(writer, json);
+                String baseJson = writer.toString();
+                output.write(baseJson.getBytes());
+                output.flush();
+            }
+        };
+    }
+    */
+
 
     @POST
     @Consumes(APPLICATION_JSON)
     @Produces(APPLICATION_JSON)
-    public Response createSubscription(final SubscriptionJson subscription,
+    public Response createSubscription(final SubscriptionJsonNoEvents subscription,
             final @QueryParam(QUERY_REQUESTED_DT) String requestedDate,
             final @QueryParam(QUERY_CALL_COMPLETION) @DefaultValue("false") Boolean callCompletion,
             final @QueryParam(QUERY_CALL_TIMEOUT) @DefaultValue("3") long timeoutSec) {
@@ -136,7 +182,7 @@ public class SubscriptionResource implements BaseJaxrsResource{
     @Produces(APPLICATION_JSON)
     @Consumes(APPLICATION_JSON)
     @Path("/{subscriptionId:" + UUID_PATTERN + "}")
-    public Response changeSubscriptionPlan(final SubscriptionJson subscription,
+    public Response changeSubscriptionPlan(final SubscriptionJsonNoEvents subscription,
             final @PathParam("subscriptionId") String subscriptionId,
             final @QueryParam(QUERY_REQUESTED_DT) String requestedDate,
             final @QueryParam(QUERY_CALL_COMPLETION) @DefaultValue("false") Boolean callCompletion,
@@ -238,29 +284,29 @@ public class SubscriptionResource implements BaseJaxrsResource{
         }
         @Override
         public void onSubscriptionTransition(SubscriptionEventTransition curEvent) {
-            log.info(String.format("Got event SubscriptionTransition token = %s, type = %s, remaining = %d ", 
+            log.debug(String.format("Got event SubscriptionTransition token = %s, type = %s, remaining = %d ", 
                     curEvent.getUserToken(), curEvent.getTransitionType(),  curEvent.getRemainingEventsForUserOperation())); 
         }
         @Override
         public void onEmptyInvoice(final EmptyInvoiceEvent curEvent) {
-            log.info(String.format("Got event EmptyInvoiceNotification token = %s ", curEvent.getUserToken())); 
+            log.debug(String.format("Got event EmptyInvoiceNotification token = %s ", curEvent.getUserToken())); 
             notifyForCompletion();
         }
         @Override
         public void onInvoiceCreation(InvoiceCreationEvent curEvent) {
-            log.info(String.format("Got event InvoiceCreationNotification token = %s ", curEvent.getUserToken())); 
+            log.debug(String.format("Got event InvoiceCreationNotification token = %s ", curEvent.getUserToken())); 
             if (curEvent.getAmountOwed().compareTo(BigDecimal.ZERO) <= 0) {
                 notifyForCompletion();
             }
         }
         @Override
         public void onPaymentInfo(PaymentInfoEvent curEvent) {
-            log.info(String.format("Got event PaymentInfo token = %s ", curEvent.getUserToken()));  
+            log.debug(String.format("Got event PaymentInfo token = %s ", curEvent.getUserToken()));  
             notifyForCompletion();
         }
         @Override
         public void onPaymentError(PaymentErrorEvent curEvent) {
-            log.info(String.format("Got event PaymentError token = %s ", curEvent.getUserToken())); 
+            log.debug(String.format("Got event PaymentError token = %s ", curEvent.getUserToken())); 
             notifyForCompletion();
         }
     }
@@ -288,10 +334,13 @@ 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/jaxrs/src/main/java/com/ning/billing/jaxrs/util/KillbillEventHandler.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/util/KillbillEventHandler.java
index 7d835e8..dc18416 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/util/KillbillEventHandler.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/util/KillbillEventHandler.java
@@ -15,6 +15,7 @@
  */
 package com.ning.billing.jaxrs.util;
 
+import java.util.ArrayList;
 import java.util.LinkedList;
 import java.util.List;
 
@@ -22,7 +23,6 @@ import com.google.common.eventbus.Subscribe;
 import com.ning.billing.util.bus.BusEvent;
 import com.ning.billing.util.userrequest.CompletionUserRequest;
 import com.ning.billing.util.userrequest.CompletionUserRequestNotifier;
-import com.ning.billing.util.userrequest.CompletionUserRequestWaiter;
 
 public class KillbillEventHandler {
     
@@ -56,10 +56,14 @@ public class KillbillEventHandler {
      */
     @Subscribe
     public void handleEntitlementevents(final BusEvent event) {
-        if (activeWaiters.size() == 0) {
+        List<CompletionUserRequestNotifier> runningWaiters = new ArrayList<CompletionUserRequestNotifier>();
+        synchronized(activeWaiters) {
+            runningWaiters.addAll(activeWaiters);
+        }
+        if (runningWaiters.size() == 0) {
             return;
         }
-        for (CompletionUserRequestNotifier cur : activeWaiters) {
+        for (CompletionUserRequestNotifier cur : runningWaiters) {
             cur.onBusEvent(event);
         }
     }
diff --git a/server/src/main/java/com/ning/billing/server/listeners/KillbillGuiceListener.java b/server/src/main/java/com/ning/billing/server/listeners/KillbillGuiceListener.java
index 224d637..3ec9e22 100644
--- a/server/src/main/java/com/ning/billing/server/listeners/KillbillGuiceListener.java
+++ b/server/src/main/java/com/ning/billing/server/listeners/KillbillGuiceListener.java
@@ -29,6 +29,8 @@ import com.ning.jetty.core.listeners.SetupServer;
 import com.google.inject.Injector;
 import com.google.inject.Module;
 
+import org.codehaus.jackson.map.ObjectMapper;
+import org.codehaus.jackson.map.SerializationConfig;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -69,7 +71,7 @@ public class KillbillGuiceListener extends SetupServer
         killbillLifecycle = theInjector.getInstance(DefaultLifecycle.class);
         killbillBusService = theInjector.getInstance(BusService.class);
         killbilleventHandler = theInjector.getInstance(KillbillEventHandler.class); 
-
+        
         //
         // Fire all Startup levels up to service start
         //
diff --git a/server/src/test/java/com/ning/billing/jaxrs/TestAccount.java b/server/src/test/java/com/ning/billing/jaxrs/TestAccount.java
index 4f0a4b2..8d971ec 100644
--- a/server/src/test/java/com/ning/billing/jaxrs/TestAccount.java
+++ b/server/src/test/java/com/ning/billing/jaxrs/TestAccount.java
@@ -16,6 +16,8 @@
 package com.ning.billing.jaxrs;
 
 
+import static org.testng.Assert.assertNotNull;
+
 import java.util.HashMap;
 import java.util.Map;
 
@@ -23,13 +25,20 @@ import java.util.Map;
 import javax.ws.rs.core.Response.Status;
 
 
+import org.joda.time.DateTime;
+import org.joda.time.Interval;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.testng.Assert;
 import org.testng.annotations.Test;
 
 
+import com.ning.billing.catalog.api.BillingPeriod;
+import com.ning.billing.catalog.api.ProductCategory;
 import com.ning.billing.jaxrs.json.AccountJson;
+import com.ning.billing.jaxrs.json.AccountTimelineJson;
+import com.ning.billing.jaxrs.json.BundleJsonNoSubsciptions;
+import com.ning.billing.jaxrs.json.SubscriptionJsonNoEvents;
 import com.ning.billing.jaxrs.resources.BaseJaxrsResource;
 import com.ning.http.client.Response;
 
@@ -91,4 +100,44 @@ public class TestAccount extends TestJaxrsBase {
 		Response response = doGet(uri, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
 		Assert.assertEquals(response.getStatusCode(), Status.NOT_FOUND.getStatusCode());
 	}
+	
+	@Test(groups="slow", enabled=true)
+	public void testAccountTimeline() throws Exception {
+	    
+	    DateTime initialDate = new DateTime(2012, 4, 25, 0, 3, 42, 0);
+        clock.setDeltaFromReality(initialDate.getMillis() - clock.getUTCNow().getMillis());
+        
+        
+	    AccountJson accountJson = createAccount("poney", "shdddqgfhwe", "poney@yahoo.com");
+	    assertNotNull(accountJson);
+	    
+	    BundleJsonNoSubsciptions bundleJson = createBundle(accountJson.getAcountId(), "996599");
+	    assertNotNull(bundleJson);
+	    
+        SubscriptionJsonNoEvents subscriptionJson = createSubscription(bundleJson.getBundleId(), "Shotgun", ProductCategory.BASE.toString(), BillingPeriod.MONTHLY.toString(), true);
+        assertNotNull(subscriptionJson);
+        
+        // MOVE AFTER TRIAL
+        Interval it = new Interval(clock.getUTCNow(), clock.getUTCNow().plusMonths(3).plusDays(1));
+        clock.addDeltaFromReality(it.toDurationMillis());
+
+        crappyWaitForLackOfProperSynchonization();
+        
+        
+        final String uri = BaseJaxrsResource.ACCOUNTS_PATH + "/" + accountJson.getAcountId() + "/" + BaseJaxrsResource.TIMELINE;
+        
+        Response response = doGet(uri, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
+        Assert.assertEquals(response.getStatusCode(), Status.OK.getStatusCode());
+        String baseJson = response.getResponseBody();
+        AccountTimelineJson objFromJson = mapper.readValue(baseJson, AccountTimelineJson.class);
+        assertNotNull(objFromJson);
+        log.info(baseJson);
+        
+        Assert.assertEquals(objFromJson.getPayments().size(), 3);
+        Assert.assertEquals(objFromJson.getInvoices().size(), 4);   
+        Assert.assertEquals(objFromJson.getBundles().size(), 1); 
+        Assert.assertEquals(objFromJson.getBundles().get(0).getSubscriptions().size(), 1);
+        Assert.assertEquals(objFromJson.getBundles().get(0).getSubscriptions().get(0).getEvents().size(), 2);        
+ 
+	}
 }
diff --git a/server/src/test/java/com/ning/billing/jaxrs/TestBundle.java b/server/src/test/java/com/ning/billing/jaxrs/TestBundle.java
index d340ab8..0d1f1cd 100644
--- a/server/src/test/java/com/ning/billing/jaxrs/TestBundle.java
+++ b/server/src/test/java/com/ning/billing/jaxrs/TestBundle.java
@@ -30,7 +30,7 @@ import org.testng.Assert;
 import org.testng.annotations.Test;
 
 import com.ning.billing.jaxrs.json.AccountJson;
-import com.ning.billing.jaxrs.json.BundleJson;
+import com.ning.billing.jaxrs.json.BundleJsonNoSubsciptions;
 import com.ning.billing.jaxrs.resources.BaseJaxrsResource;
 import com.ning.http.client.Response;
 
@@ -44,7 +44,7 @@ public class TestBundle extends TestJaxrsBase {
 	public void testBundleOk() throws Exception {
 
 		AccountJson accountJson = createAccount("xlxl", "shdgfhkkl", "xlxl@yahoo.com");
-		BundleJson bundleJson = createBundle(accountJson.getAcountId(), "12345");
+		BundleJsonNoSubsciptions bundleJson = createBundle(accountJson.getAcountId(), "12345");
 		
 		// Retrieves by external key
 		Map<String, String> queryParams = new HashMap<String, String>();
@@ -52,7 +52,7 @@ public class TestBundle extends TestJaxrsBase {
 		Response response = doGet(BaseJaxrsResource.BUNDLES_PATH, queryParams, DEFAULT_HTTP_TIMEOUT_SEC);
 		Assert.assertEquals(response.getStatusCode(), Status.OK.getStatusCode());
 		String baseJson = response.getResponseBody();
-		BundleJson objFromJson = mapper.readValue(baseJson, BundleJson.class);
+		BundleJsonNoSubsciptions objFromJson = mapper.readValue(baseJson, BundleJsonNoSubsciptions.class);
 		Assert.assertTrue(objFromJson.equals(bundleJson));
 	}
 	
@@ -61,18 +61,18 @@ public class TestBundle extends TestJaxrsBase {
 	public void testBundleFromAccount() throws Exception {
 
 		AccountJson accountJson = createAccount("xaxa", "saagfhkkl", "xaxa@yahoo.com");
-		BundleJson bundleJson1 = createBundle(accountJson.getAcountId(), "156567");
-		BundleJson bundleJson2 = createBundle(accountJson.getAcountId(), "265658");
+		BundleJsonNoSubsciptions bundleJson1 = createBundle(accountJson.getAcountId(), "156567");
+		BundleJsonNoSubsciptions bundleJson2 = createBundle(accountJson.getAcountId(), "265658");
 
 		String uri = BaseJaxrsResource.ACCOUNTS_PATH + "/" + accountJson.getAcountId().toString() + "/" + BaseJaxrsResource.BUNDLES;
 		Response response = doGet(uri, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
 		Assert.assertEquals(response.getStatusCode(), Status.OK.getStatusCode());
 		String baseJson = response.getResponseBody();
-		List<BundleJson> objFromJson = mapper.readValue(baseJson, new TypeReference<List<BundleJson>>() {});
+		List<BundleJsonNoSubsciptions> objFromJson = mapper.readValue(baseJson, new TypeReference<List<BundleJsonNoSubsciptions>>() {});
 		
-		Collections.sort(objFromJson, new Comparator<BundleJson>() {
+		Collections.sort(objFromJson, new Comparator<BundleJsonNoSubsciptions>() {
 			@Override
-			public int compare(BundleJson o1, BundleJson o2) {
+			public int compare(BundleJsonNoSubsciptions o1, BundleJsonNoSubsciptions o2) {
 				return o1.getExternalKey().compareTo(o2.getExternalKey());
 			}
 		});
@@ -100,7 +100,7 @@ public class TestBundle extends TestJaxrsBase {
 		response = doGet(uri, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
 		Assert.assertEquals(response.getStatusCode(), Status.OK.getStatusCode());
 		String baseJson = response.getResponseBody();
-		List<BundleJson> objFromJson = mapper.readValue(baseJson, new TypeReference<List<BundleJson>>() {});
+		List<BundleJsonNoSubsciptions> objFromJson = mapper.readValue(baseJson, new TypeReference<List<BundleJsonNoSubsciptions>>() {});
 		Assert.assertNotNull(objFromJson);
 		Assert.assertEquals(objFromJson.size(), 0);
 	}
diff --git a/server/src/test/java/com/ning/billing/jaxrs/TestJaxrsBase.java b/server/src/test/java/com/ning/billing/jaxrs/TestJaxrsBase.java
index f81baba..4eb1f56 100644
--- a/server/src/test/java/com/ning/billing/jaxrs/TestJaxrsBase.java
+++ b/server/src/test/java/com/ning/billing/jaxrs/TestJaxrsBase.java
@@ -58,8 +58,8 @@ import com.ning.billing.dbi.MysqlTestingHelper;
 import com.ning.billing.entitlement.glue.EntitlementModule;
 import com.ning.billing.invoice.glue.InvoiceModule;
 import com.ning.billing.jaxrs.json.AccountJson;
-import com.ning.billing.jaxrs.json.BundleJson;
-import com.ning.billing.jaxrs.json.SubscriptionJson;
+import com.ning.billing.jaxrs.json.BundleJsonNoSubsciptions;
+import com.ning.billing.jaxrs.json.SubscriptionJsonNoEvents;
 import com.ning.billing.jaxrs.resources.BaseJaxrsResource;
 import com.ning.billing.junction.glue.JunctionModule;
 import com.ning.billing.payment.provider.MockPaymentProviderPluginModule;
@@ -132,7 +132,7 @@ public class TestJaxrsBase {
         }
         
         //
-        // Listener is created once befire Suite and keeps pointer to helper and clock so they can get
+        // Listener is created once before Suite and keeps pointer to helper and clock so they can get
         // reset for each test Class-- needed in order to ONLY start Jetty once across all the test classes
         // while still being able to start mysql before Jetty is started
         //
@@ -229,6 +229,7 @@ public class TestJaxrsBase {
         final String invoiceDdl = IOUtils.toString(TestIntegration.class.getResourceAsStream("/com/ning/billing/invoice/ddl.sql"));
         final String paymentDdl = IOUtils.toString(TestIntegration.class.getResourceAsStream("/com/ning/billing/payment/ddl.sql"));
         final String utilDdl = IOUtils.toString(TestIntegration.class.getResourceAsStream("/com/ning/billing/util/ddl.sql"));
+        final String analyticsDdl = IOUtils.toString(TestIntegration.class.getResourceAsStream("/com/ning/billing/analytics/ddl.sql"));        
 
         helper.startMysql();
 
@@ -237,6 +238,7 @@ public class TestJaxrsBase {
         helper.initDb(invoiceDdl);
         helper.initDb(paymentDdl);
         helper.initDb(utilDdl);
+        helper.initDb(analyticsDdl);        
     }
 
 
@@ -307,8 +309,8 @@ public class TestJaxrsBase {
 
 
 
-    protected BundleJson createBundle(String accountId, String key) throws Exception {
-        BundleJson input = new BundleJson(null, accountId, key, null);
+    protected BundleJsonNoSubsciptions createBundle(String accountId, String key) throws Exception {
+        BundleJsonNoSubsciptions input = new BundleJsonNoSubsciptions(null, accountId, key, null);
         String baseJson = mapper.writeValueAsString(input);
         Response response = doPost(BaseJaxrsResource.BUNDLES_PATH, baseJson, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
         Assert.assertEquals(response.getStatusCode(), Status.CREATED.getStatusCode());
@@ -321,14 +323,14 @@ public class TestJaxrsBase {
         Assert.assertEquals(response.getStatusCode(), Status.OK.getStatusCode());
 
         baseJson = response.getResponseBody();
-        BundleJson objFromJson = mapper.readValue(baseJson, BundleJson.class);
+        BundleJsonNoSubsciptions objFromJson = mapper.readValue(baseJson, BundleJsonNoSubsciptions.class);
         Assert.assertTrue(objFromJson.equalsNoId(input));
         return objFromJson;
     }
 
-    protected SubscriptionJson createSubscription(final String bundleId, final String productName, final String productCategory, final String billingPeriod, final boolean waitCompletion) throws Exception {
+    protected SubscriptionJsonNoEvents createSubscription(final String bundleId, final String productName, final String productCategory, final String billingPeriod, final boolean waitCompletion) throws Exception {
 
-        SubscriptionJson input = new SubscriptionJson(null, bundleId, productName, productCategory, billingPeriod, PriceListSet.DEFAULT_PRICELIST_NAME, null, null, null);
+        SubscriptionJsonNoEvents input = new SubscriptionJsonNoEvents(null, bundleId, null, productName, productCategory, billingPeriod, PriceListSet.DEFAULT_PRICELIST_NAME, null);
         String baseJson = mapper.writeValueAsString(input);
 
 
@@ -345,7 +347,7 @@ public class TestJaxrsBase {
         Assert.assertEquals(response.getStatusCode(), Status.OK.getStatusCode());
 
         baseJson = response.getResponseBody();
-        SubscriptionJson objFromJson = mapper.readValue(baseJson, SubscriptionJson.class);
+        SubscriptionJsonNoEvents objFromJson = mapper.readValue(baseJson, SubscriptionJsonNoEvents.class);
         Assert.assertTrue(objFromJson.equalsNoId(input));
         return objFromJson;
     }
@@ -450,4 +452,14 @@ public class TestJaxrsBase {
         AccountJson accountJson = new AccountJson(accountId, name, length, externalKey, email, billCycleDay, currency, paymentProvider, timeZone, address1, address2, company, state, country, phone);
         return accountJson;
     }
+    
+    /**
+     * 
+     * We could implement a ClockResource in jaxrs with the ability to sync on user token
+     * but until we have a strong need for it, this is in the TODO list...
+     */
+    protected void crappyWaitForLackOfProperSynchonization() throws Exception {
+        Thread.sleep(5000);
+    }
+
 }
diff --git a/server/src/test/java/com/ning/billing/jaxrs/TestSubscription.java b/server/src/test/java/com/ning/billing/jaxrs/TestSubscription.java
index 3bd2524..d520d49 100644
--- a/server/src/test/java/com/ning/billing/jaxrs/TestSubscription.java
+++ b/server/src/test/java/com/ning/billing/jaxrs/TestSubscription.java
@@ -15,11 +15,16 @@
  */
 package com.ning.billing.jaxrs;
 
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
 import java.util.Map;
+import java.util.UUID;
 
 import javax.ws.rs.core.Response.Status;
 
 import org.joda.time.DateTime;
+import org.joda.time.Interval;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.testng.Assert;
@@ -27,11 +32,12 @@ import org.testng.annotations.Test;
 
 import com.ning.billing.catalog.api.BillingPeriod;
 import com.ning.billing.catalog.api.Duration;
+import com.ning.billing.catalog.api.PriceListSet;
 import com.ning.billing.catalog.api.ProductCategory;
 import com.ning.billing.catalog.api.TimeUnit;
 import com.ning.billing.jaxrs.json.AccountJson;
-import com.ning.billing.jaxrs.json.BundleJson;
-import com.ning.billing.jaxrs.json.SubscriptionJson;
+import com.ning.billing.jaxrs.json.BundleJsonNoSubsciptions;
+import com.ning.billing.jaxrs.json.SubscriptionJsonNoEvents;
 import com.ning.billing.jaxrs.resources.BaseJaxrsResource;
 import com.ning.http.client.Response;
 
@@ -39,54 +45,57 @@ public class TestSubscription extends TestJaxrsBase {
 
     private static final Logger log = LoggerFactory.getLogger(TestSubscription.class);
 
-    private static final long DELAY = 5000;
     private static final String CALL_COMPLETION_TIMEOUT_SEC = "5";
     
 
     @Test(groups="slow", enabled=true)
     public void testSubscriptionInTrialOk() throws Exception {
 
+        DateTime initialDate = new DateTime(2012, 4, 25, 0, 3, 42, 0);
+        clock.setDeltaFromReality(initialDate.getMillis() - clock.getUTCNow().getMillis());
+        
         AccountJson accountJson = createAccount("xil", "shdxilhkkl", "xil@yahoo.com");
-        BundleJson bundleJson = createBundle(accountJson.getAcountId(), "99999");
+        BundleJsonNoSubsciptions bundleJson = createBundle(accountJson.getAcountId(), "99999");
 
         String productName = "Shotgun";
         BillingPeriod term = BillingPeriod.MONTHLY;
 
-        SubscriptionJson subscriptionJson = createSubscription(bundleJson.getBundleId(), productName, ProductCategory.BASE.toString(), term.toString(), true);
-
+        SubscriptionJsonNoEvents subscriptionJson = createSubscription(bundleJson.getBundleId(), productName, ProductCategory.BASE.toString(), term.toString(), true);
+        Assert.assertNotNull(subscriptionJson.getChargedThroughDate());
+        Assert.assertEquals(subscriptionJson.getChargedThroughDate(), subscriptionJson.getStartDate().plusDays(30));        
+        
+        String uri = BaseJaxrsResource.SUBSCRIPTIONS_PATH + "/" + subscriptionJson.getSubscriptionId().toString();
+ 
+        
+        // Retrieves with GET
+        Response response =  doGet(uri, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
+        assertEquals(response.getStatusCode(), Status.OK.getStatusCode());
+        String baseJson = response.getResponseBody();
+        SubscriptionJsonNoEvents objFromJson = mapper.readValue(baseJson, SubscriptionJsonNoEvents.class);
+        Assert.assertTrue(objFromJson.equals(subscriptionJson));
+        
         // Change plan IMM
         String newProductName = "Assault-Rifle";
 
-        SubscriptionJson newInput = new SubscriptionJson(subscriptionJson.getSubscriptionId(),
+        SubscriptionJsonNoEvents newInput = new SubscriptionJsonNoEvents(subscriptionJson.getSubscriptionId(),
                 subscriptionJson.getBundleId(),
+                null,
                 newProductName,
                 subscriptionJson.getProductCategory(), 
                 subscriptionJson.getBillingPeriod(), 
-                subscriptionJson.getPriceList(), null, null, null);
-        String baseJson = mapper.writeValueAsString(newInput);
+                subscriptionJson.getPriceList(), null);
+        baseJson = mapper.writeValueAsString(newInput);
 
-        String uri = BaseJaxrsResource.SUBSCRIPTIONS_PATH + "/" + subscriptionJson.getSubscriptionId().toString();
         Map<String, String> queryParams = getQueryParamsForCallCompletion(CALL_COMPLETION_TIMEOUT_SEC);
-        Response response = doPut(uri, baseJson, queryParams, DEFAULT_HTTP_TIMEOUT_SEC);
-        Assert.assertEquals(response.getStatusCode(), Status.OK.getStatusCode());
+        response = doPut(uri, baseJson, queryParams, DEFAULT_HTTP_TIMEOUT_SEC);
+        assertEquals(response.getStatusCode(), Status.OK.getStatusCode());
         baseJson = response.getResponseBody();
-        SubscriptionJson objFromJson = mapper.readValue(baseJson, SubscriptionJson.class);
-        Assert.assertTrue(objFromJson.equals(newInput));
-
-        clock.setDeltaFromReality(new Duration() {
-            @Override
-            public TimeUnit getUnit() {
-                return TimeUnit.MONTHS;
-            }
-            @Override
-            public int getNumber() {
-                return 1;
-            }
-            @Override
-            public DateTime addToDateTime(DateTime dateTime) {
-                return null;
-            }
-        }, 1000);
+        objFromJson = mapper.readValue(baseJson, SubscriptionJsonNoEvents.class);
+        assertTrue(objFromJson.equals(newInput));
+
+        // MOVE AFTER TRIAL
+        Interval it = new Interval(clock.getUTCNow(), clock.getUTCNow().plusMonths(3).plusDays(1));
+        clock.addDeltaFromReality(it.toDurationMillis());
 
         crappyWaitForLackOfProperSynchonization();
 
@@ -94,22 +103,32 @@ public class TestSubscription extends TestJaxrsBase {
         // Cancel EOT
         uri = BaseJaxrsResource.SUBSCRIPTIONS_PATH + "/" + subscriptionJson.getSubscriptionId().toString();
         response = doDelete(uri, queryParams, DEFAULT_HTTP_TIMEOUT_SEC);
-        Assert.assertEquals(response.getStatusCode(), Status.OK.getStatusCode());
+        assertEquals(response.getStatusCode(), Status.OK.getStatusCode());
 
         // Uncancel
         uri = BaseJaxrsResource.SUBSCRIPTIONS_PATH + "/" + subscriptionJson.getSubscriptionId().toString() + "/uncancel";
         response = doPut(uri, baseJson, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
         Assert.assertEquals(response.getStatusCode(), Status.OK.getStatusCode());
     }
- 
-
-    /**
-     * 
-     * We could implement a ClockResource in jaxrs with the ability to sync on user token
-     * but until we have a strong need for it, this is in the TODO list...
-     */
-    private void crappyWaitForLackOfProperSynchonization() throws Exception {
-        Thread.sleep(DELAY);
+    
+    @Test(groups="slow", enabled=true)
+    public void testWithNonExistentSubscription() throws Exception {
+        String uri = BaseJaxrsResource.SUBSCRIPTIONS_PATH + "/" + UUID.randomUUID().toString();
+        SubscriptionJsonNoEvents subscriptionJson = new SubscriptionJsonNoEvents(null, UUID.randomUUID().toString(), null, "Pistol", ProductCategory.BASE.toString(), BillingPeriod.MONTHLY.toString(), PriceListSet.DEFAULT_PRICELIST_NAME, null);
+        String baseJson = mapper.writeValueAsString(subscriptionJson);
+        
+        Response response = doPut(uri, baseJson, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
+        Assert.assertEquals(response.getStatusCode(), Status.NO_CONTENT.getStatusCode());
+        String body = response.getResponseBody();
+        Assert.assertEquals(body, "");
+        
+        response = doDelete(uri, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
+        Assert.assertEquals(response.getStatusCode(), Status.NO_CONTENT.getStatusCode());
+        body = response.getResponseBody();
+        Assert.assertEquals(body, "");
+        
+        response =  doGet(uri, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
+        Assert.assertEquals(response.getStatusCode(), Status.NO_CONTENT.getStatusCode());
     }
 
 }