killbill-aplcache

Changes

account/src/main/java/com/ning/billing/account/dao/FieldStoreDaoWrapper.java 47(+0 -47)

account/src/main/java/com/ning/billing/account/dao/TagStoreDaoWrapper.java 46(+0 -46)

Details

diff --git a/account/src/main/java/com/ning/billing/account/api/DefaultAccount.java b/account/src/main/java/com/ning/billing/account/api/DefaultAccount.java
index a3fbf4e..d3588fa 100644
--- a/account/src/main/java/com/ning/billing/account/api/DefaultAccount.java
+++ b/account/src/main/java/com/ning/billing/account/api/DefaultAccount.java
@@ -22,6 +22,11 @@ import java.util.UUID;
 import org.joda.time.DateTime;
 
 import com.ning.billing.catalog.api.Currency;
+import com.ning.billing.util.customfield.CustomizableEntityBase;
+import com.ning.billing.util.tag.DefaultTag;
+import com.ning.billing.util.tag.DefaultTagStore;
+import com.ning.billing.util.tag.Tag;
+import com.ning.billing.util.tag.TagDescription;
 
 public class DefaultAccount extends CustomizableEntityBase implements Account {
     public final static String OBJECT_TYPE = "Account";
@@ -42,6 +47,12 @@ public class DefaultAccount extends CustomizableEntityBase implements Account {
                 data.getPaymentProviderName());
     }
 
+    public DefaultAccount(UUID id, AccountData data) {
+        this(id, data.getExternalKey(), data.getEmail(), data.getName(),
+                data.getFirstNameLength(), data.getPhone(), data.getCurrency(), data.getBillCycleDay(),
+                data.getPaymentProviderName());
+    }
+
     public DefaultAccount(UUID id, String externalKey, String email, String name, int firstNameLength,
                           String phone, Currency currency, int billCycleDay, String paymentProviderName) {
         super(id);
diff --git a/account/src/main/java/com/ning/billing/account/api/user/DefaultAccountUserApi.java b/account/src/main/java/com/ning/billing/account/api/user/DefaultAccountUserApi.java
index a3b26fc..497d139 100644
--- a/account/src/main/java/com/ning/billing/account/api/user/DefaultAccountUserApi.java
+++ b/account/src/main/java/com/ning/billing/account/api/user/DefaultAccountUserApi.java
@@ -16,15 +16,14 @@
 
 package com.ning.billing.account.api.user;
 
+import java.util.List;
+import java.util.UUID;
 import com.google.inject.Inject;
 import com.ning.billing.account.api.Account;
 import com.ning.billing.account.api.AccountData;
 import com.ning.billing.account.api.DefaultAccount;
 import com.ning.billing.account.dao.AccountDao;
 
-import java.util.List;
-import java.util.UUID;
-
 public class DefaultAccountUserApi implements com.ning.billing.account.api.AccountUserApi {
     private final AccountDao dao;
 
diff --git a/account/src/main/java/com/ning/billing/account/dao/AccountDao.java b/account/src/main/java/com/ning/billing/account/dao/AccountDao.java
index c6cfbf3..52d43ab 100644
--- a/account/src/main/java/com/ning/billing/account/dao/AccountDao.java
+++ b/account/src/main/java/com/ning/billing/account/dao/AccountDao.java
@@ -17,81 +17,8 @@
 package com.ning.billing.account.dao;
 
 import com.ning.billing.account.api.Account;
-import com.ning.billing.account.api.DefaultAccount;
-import com.ning.billing.account.api.user.AccountBuilder;
-import com.ning.billing.catalog.api.Currency;
-import org.skife.jdbi.v2.SQLStatement;
-import org.skife.jdbi.v2.StatementContext;
-import org.skife.jdbi.v2.sqlobject.Bind;
-import org.skife.jdbi.v2.sqlobject.Binder;
-import org.skife.jdbi.v2.sqlobject.BinderFactory;
-import org.skife.jdbi.v2.sqlobject.BindingAnnotation;
-import org.skife.jdbi.v2.sqlobject.SqlQuery;
-import org.skife.jdbi.v2.sqlobject.SqlUpdate;
-import org.skife.jdbi.v2.sqlobject.customizers.RegisterMapper;
-import org.skife.jdbi.v2.sqlobject.stringtemplate.ExternalizedSqlViaStringTemplate3;
-import org.skife.jdbi.v2.tweak.ResultSetMapper;
+import com.ning.billing.util.entity.EntityDao;
 
-import java.lang.annotation.Annotation;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.util.UUID;
-
-@ExternalizedSqlViaStringTemplate3
-@RegisterMapper(AccountDaoWrapper.AccountMapper.class)
 public interface AccountDao extends EntityDao<Account> {
-    @SqlQuery
-    public Account getAccountByKey(@Bind("externalKey") final String key);
-
-    @Override
-    @SqlUpdate
-    public void save(@AccountBinder Account account);
-
-    public static class AccountMapper implements ResultSetMapper<Account> {
-        @Override
-        public Account map(int index, ResultSet result, StatementContext context) throws SQLException {
-            UUID id = UUID.fromString(result.getString("id"));
-            String externalKey = result.getString("external_key");
-            String email = result.getString("email");
-            String name = result.getString("name");
-            int firstNameLength = result.getInt("first_name_length");
-            String phone = result.getString("phone");
-            int billingCycleDay = result.getInt("billing_cycle_day");
-            Currency currency = Currency.valueOf(result.getString("currency"));
-            String paymentProviderName = result.getString("payment_provider_name");
-
-            return new AccountBuilder(id).externalKey(externalKey).email(email)
-                                         .name(name).firstNameLength(firstNameLength)
-                                         .phone(phone).currency(currency)
-                                         .billingCycleDay(billingCycleDay)
-                                         .paymentProviderName(paymentProviderName).build();
-        }
-    }
-
-    @BindingAnnotation(AccountBinder.AccountBinderFactory.class)
-    @Retention(RetentionPolicy.RUNTIME)
-    @Target({ElementType.PARAMETER})
-    public @interface AccountBinder {
-        public static class AccountBinderFactory implements BinderFactory {
-            public Binder build(Annotation annotation) {
-                return new Binder<AccountBinder, DefaultAccount>() {
-                    public void bind(SQLStatement q, AccountBinder bind, DefaultAccount account) {
-                        q.bind("id", account.getId().toString());
-                        q.bind("externalKey", account.getExternalKey());
-                        q.bind("email", account.getEmail());
-                        q.bind("name", account.getName());
-                        q.bind("firstNameLength", account.getFirstNameLength());
-                        q.bind("phone", account.getPhone());
-                        q.bind("currency", account.getCurrency().toString());
-                        q.bind("billingCycleDay", account.getBillCycleDay());
-                        q.bind("paymentProviderName", account.getPaymentProviderName());
-                    }
-                };
-            }
-        }
-    }
+    public Account getAccountByKey(String key);
 }
diff --git a/account/src/main/java/com/ning/billing/account/dao/AccountSqlDao.java b/account/src/main/java/com/ning/billing/account/dao/AccountSqlDao.java
new file mode 100644
index 0000000..4c2a550
--- /dev/null
+++ b/account/src/main/java/com/ning/billing/account/dao/AccountSqlDao.java
@@ -0,0 +1,100 @@
+/*
+ * 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.account.dao;
+
+import com.ning.billing.account.api.Account;
+import com.ning.billing.account.api.AccountData;
+import com.ning.billing.account.api.user.AccountBuilder;
+import com.ning.billing.catalog.api.Currency;
+import com.ning.billing.util.entity.EntityDao;
+import org.skife.jdbi.v2.SQLStatement;
+import org.skife.jdbi.v2.StatementContext;
+import org.skife.jdbi.v2.sqlobject.Bind;
+import org.skife.jdbi.v2.sqlobject.Binder;
+import org.skife.jdbi.v2.sqlobject.BinderFactory;
+import org.skife.jdbi.v2.sqlobject.BindingAnnotation;
+import org.skife.jdbi.v2.sqlobject.SqlQuery;
+import org.skife.jdbi.v2.sqlobject.SqlUpdate;
+import org.skife.jdbi.v2.sqlobject.customizers.RegisterMapper;
+import org.skife.jdbi.v2.sqlobject.mixins.Transactional;
+import org.skife.jdbi.v2.sqlobject.mixins.Transmogrifier;
+import org.skife.jdbi.v2.sqlobject.stringtemplate.ExternalizedSqlViaStringTemplate3;
+import org.skife.jdbi.v2.tweak.ResultSetMapper;
+
+import java.lang.annotation.Annotation;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.UUID;
+
+@ExternalizedSqlViaStringTemplate3
+@RegisterMapper(AccountSqlDao.AccountMapper.class)
+public interface AccountSqlDao extends EntityDao<Account>, Transactional<AccountSqlDao>, Transmogrifier {
+    @SqlQuery
+    public Account getAccountByKey(@Bind("externalKey") final String key);
+
+    @Override
+    @SqlUpdate
+    public void save(@AccountBinder Account account);
+
+    public static class AccountMapper implements ResultSetMapper<Account> {
+        @Override
+        public Account map(int index, ResultSet result, StatementContext context) throws SQLException {
+            UUID id = UUID.fromString(result.getString("id"));
+            String externalKey = result.getString("external_key");
+            String email = result.getString("email");
+            String name = result.getString("name");
+            int firstNameLength = result.getInt("first_name_length");
+            String phone = result.getString("phone");
+            int billingCycleDay = result.getInt("billing_cycle_day");
+            Currency currency = Currency.valueOf(result.getString("currency"));
+            String paymentProviderName = result.getString("payment_provider_name");
+
+            return new AccountBuilder(id).externalKey(externalKey).email(email)
+                                         .name(name).firstNameLength(firstNameLength)
+                                         .phone(phone).currency(currency)
+                                         .billingCycleDay(billingCycleDay)
+                                         .paymentProviderName(paymentProviderName).build();
+        }
+    }
+
+    @BindingAnnotation(AccountBinder.AccountBinderFactory.class)
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target({ElementType.PARAMETER})
+    public @interface AccountBinder {
+        public static class AccountBinderFactory implements BinderFactory {
+            public Binder build(Annotation annotation) {
+                return new Binder<AccountBinder, AccountData>() {
+                    public void bind(SQLStatement q, AccountBinder bind, AccountData account) {
+                        q.bind("id", account.getId().toString());
+                        q.bind("externalKey", account.getExternalKey());
+                        q.bind("email", account.getEmail());
+                        q.bind("name", account.getName());
+                        q.bind("firstNameLength", account.getFirstNameLength());
+                        q.bind("phone", account.getPhone());
+                        q.bind("currency", account.getCurrency().toString());
+                        q.bind("billingCycleDay", account.getBillCycleDay());
+                        q.bind("paymentProviderName", account.getPaymentProviderName());
+                    }
+                };
+            }
+        }
+    }
+}
diff --git a/account/src/main/java/com/ning/billing/account/glue/AccountModule.java b/account/src/main/java/com/ning/billing/account/glue/AccountModule.java
index 5c191c2..d70548d 100644
--- a/account/src/main/java/com/ning/billing/account/glue/AccountModule.java
+++ b/account/src/main/java/com/ning/billing/account/glue/AccountModule.java
@@ -20,11 +20,8 @@ import com.google.inject.AbstractModule;
 import com.ning.billing.account.api.AccountUserApi;
 import com.ning.billing.account.api.user.DefaultAccountUserApi;
 import com.ning.billing.account.dao.AccountDao;
-import com.ning.billing.account.dao.AccountDaoWrapper;
-import com.ning.billing.account.dao.FieldStoreDao;
-import com.ning.billing.account.dao.FieldStoreDaoWrapper;
-import com.ning.billing.account.dao.TagStoreDao;
-import com.ning.billing.account.dao.TagStoreDaoWrapper;
+import com.ning.billing.account.dao.AccountSqlDao;
+import com.ning.billing.account.dao.DefaultAccountDao;
 import org.skife.config.ConfigurationObjectFactory;
 
 public class AccountModule extends AbstractModule {
@@ -40,28 +37,18 @@ public class AccountModule extends AbstractModule {
     }
 
     private void installAccountDao() {
-        bind(AccountDao.class).to(AccountDaoWrapper.class).asEagerSingleton();
+        bind(AccountDao.class).to(DefaultAccountDao.class).asEagerSingleton();
     }
 
     private void installAccountUserApi() {
         bind(AccountUserApi.class).to(DefaultAccountUserApi.class).asEagerSingleton();
     }
 
-//    private void installFieldStore() {
-//        bind(FieldStoreDao.class).to(FieldStoreDaoWrapper.class).asEagerSingleton();
-//    }
-//
-//    private void installTagStore() {
-//        bind(TagStoreDao.class).to(TagStoreDaoWrapper.class).asEagerSingleton();
-//    }
-
     @Override
     protected void configure() {
         installConfig();
         installAccountCore();
         installAccountDao();
         installAccountUserApi();
-//        installFieldStore();
-//        installTagStore();
     }
 }
diff --git a/account/src/main/resources/com/ning/billing/account/ddl.sql b/account/src/main/resources/com/ning/billing/account/ddl.sql
index 9bc2a03..42cf2ef 100644
--- a/account/src/main/resources/com/ning/billing/account/ddl.sql
+++ b/account/src/main/resources/com/ning/billing/account/ddl.sql
@@ -8,7 +8,7 @@ CREATE TABLE accounts (
     phone varchar(13) DEFAULT NULL,
     currency char(3) NOT NULL,
     billing_cycle_day int NOT NULL,
-    payment_provider_name varchar(20),
+    payment_provider_name varchar(20) DEFAULT NULL,
     PRIMARY KEY(id)
 ) ENGINE=innodb;
 CREATE UNIQUE INDEX accounts_external_key ON accounts(external_key);
diff --git a/account/src/test/java/com/ning/billing/account/dao/AccountDaoTestBase.java b/account/src/test/java/com/ning/billing/account/dao/AccountDaoTestBase.java
index d191a0e..ce9570f 100644
--- a/account/src/test/java/com/ning/billing/account/dao/AccountDaoTestBase.java
+++ b/account/src/test/java/com/ning/billing/account/dao/AccountDaoTestBase.java
@@ -40,7 +40,7 @@ public abstract class AccountDaoTestBase {
         // Healthcheck test to make sure MySQL is setup properly
         try {
             AccountModuleMock module = new AccountModuleMock();
-            final String ddl = IOUtils.toString(AccountDao.class.getResourceAsStream("/com/ning/billing/account/ddl.sql"));
+            final String ddl = IOUtils.toString(AccountSqlDao.class.getResourceAsStream("/com/ning/billing/account/ddl.sql"));
             module.createDb(ddl);
 
             final Injector injector = Guice.createInjector(Stage.DEVELOPMENT, module);
diff --git a/account/src/test/java/com/ning/billing/account/dao/TestFieldStore.java b/account/src/test/java/com/ning/billing/account/dao/TestFieldStore.java
index 398df58..fa84b54 100644
--- a/account/src/test/java/com/ning/billing/account/dao/TestFieldStore.java
+++ b/account/src/test/java/com/ning/billing/account/dao/TestFieldStore.java
@@ -18,8 +18,9 @@ package com.ning.billing.account.dao;
 
 import java.util.UUID;
 import org.testng.annotations.Test;
-import com.ning.billing.account.api.DefaultFieldStore;
-import com.ning.billing.account.api.FieldStore;
+import com.ning.billing.util.customfield.DefaultFieldStore;
+import com.ning.billing.util.customfield.FieldStore;
+import com.ning.billing.util.customfield.dao.FieldStoreDao;
 
 import static org.testng.Assert.assertEquals;
 
diff --git a/account/src/test/java/com/ning/billing/account/dao/TestSimpleAccountDao.java b/account/src/test/java/com/ning/billing/account/dao/TestSimpleAccountDao.java
index 33b67d8..0deec50 100644
--- a/account/src/test/java/com/ning/billing/account/dao/TestSimpleAccountDao.java
+++ b/account/src/test/java/com/ning/billing/account/dao/TestSimpleAccountDao.java
@@ -22,12 +22,14 @@ import org.joda.time.DateTime;
 import org.testng.annotations.Test;
 import com.ning.billing.account.api.Account;
 import com.ning.billing.account.api.DefaultAccount;
-import com.ning.billing.account.api.DefaultTagDescription;
-import com.ning.billing.account.api.Tag;
-import com.ning.billing.account.api.TagDescription;
+import com.ning.billing.util.tag.DefaultTagDescription;
+import com.ning.billing.util.tag.Tag;
+import com.ning.billing.util.tag.TagDescription;
 import com.ning.billing.account.api.user.AccountBuilder;
 import com.ning.billing.catalog.api.Currency;
 import com.ning.billing.util.clock.DefaultClock;
+import com.ning.billing.util.tag.dao.TagDescriptionDao;
+import com.ning.billing.util.tag.dao.TagDescriptionDao;
 
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertNotNull;
diff --git a/api/src/main/java/com/ning/billing/account/api/Account.java b/api/src/main/java/com/ning/billing/account/api/Account.java
index 9efce90..1cc9aa9 100644
--- a/api/src/main/java/com/ning/billing/account/api/Account.java
+++ b/api/src/main/java/com/ning/billing/account/api/Account.java
@@ -16,6 +16,9 @@
 
 package com.ning.billing.account.api;
 
+import com.ning.billing.util.customfield.CustomizableEntity;
+import com.ning.billing.util.tag.Taggable;
+
 public interface Account extends AccountData, CustomizableEntity, Taggable {
 
 }
diff --git a/api/src/main/java/com/ning/billing/account/api/AccountData.java b/api/src/main/java/com/ning/billing/account/api/AccountData.java
index cdcae52..87d71c1 100644
--- a/api/src/main/java/com/ning/billing/account/api/AccountData.java
+++ b/api/src/main/java/com/ning/billing/account/api/AccountData.java
@@ -17,8 +17,9 @@
 package com.ning.billing.account.api;
 
 import com.ning.billing.catalog.api.Currency;
+import com.ning.billing.util.entity.Entity;
 
-public interface AccountData extends Entity{
+public interface AccountData extends Entity {
 
     public String getExternalKey();
 
diff --git a/api/src/main/java/com/ning/billing/ErrorCode.java b/api/src/main/java/com/ning/billing/ErrorCode.java
index 8fc3df4..8336ddb 100644
--- a/api/src/main/java/com/ning/billing/ErrorCode.java
+++ b/api/src/main/java/com/ning/billing/ErrorCode.java
@@ -33,7 +33,7 @@ public enum ErrorCode {
 
     /* Creation */
     ENT_CREATE_BAD_PHASE(1011, "Can't create plan initial phase %s"),
-    ENT_CREATE_NO_BUNDLE(1012, "Bundle %s does not exists"),
+    ENT_CREATE_NO_BUNDLE(1012, "Bundle %s does not exist"),
     ENT_CREATE_NO_BP(1013, "Missing Base Subscription for bundle %s"),
     ENT_CREATE_BP_EXISTS(1015, "Subscription bundle %s already has a base subscription"),
     /* Change plan */
diff --git a/api/src/main/java/com/ning/billing/invoice/api/Invoice.java b/api/src/main/java/com/ning/billing/invoice/api/Invoice.java
index 41d7adb..4c7d6fd 100644
--- a/api/src/main/java/com/ning/billing/invoice/api/Invoice.java
+++ b/api/src/main/java/com/ning/billing/invoice/api/Invoice.java
@@ -16,6 +16,7 @@
 
 package com.ning.billing.invoice.api;
 
+import com.ning.billing.util.entity.Entity;
 import com.ning.billing.catalog.api.Currency;
 import org.joda.time.DateTime;
 
@@ -23,7 +24,7 @@ import java.math.BigDecimal;
 import java.util.List;
 import java.util.UUID;
 
-public interface Invoice {
+public interface Invoice extends Entity {
     boolean add(InvoiceItem item);
 
     boolean add(List<InvoiceItem> items);
@@ -32,8 +33,6 @@ public interface Invoice {
 
     int getNumberOfItems();
 
-    UUID getId();
-
     UUID getAccountId();
 
     DateTime getInvoiceDate();
diff --git a/api/src/main/java/com/ning/billing/invoice/api/InvoiceItem.java b/api/src/main/java/com/ning/billing/invoice/api/InvoiceItem.java
index bce002a..44c46a7 100644
--- a/api/src/main/java/com/ning/billing/invoice/api/InvoiceItem.java
+++ b/api/src/main/java/com/ning/billing/invoice/api/InvoiceItem.java
@@ -17,14 +17,13 @@
 package com.ning.billing.invoice.api;
 
 import com.ning.billing.catalog.api.Currency;
+import com.ning.billing.util.entity.Entity;
 import org.joda.time.DateTime;
 
 import java.math.BigDecimal;
 import java.util.UUID;
 
-public interface InvoiceItem extends Comparable<InvoiceItem> {
-    UUID getId();
-
+public interface InvoiceItem extends Entity, Comparable<InvoiceItem> {
     UUID getInvoiceId();
 
     UUID getSubscriptionId();
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/BundleSqlDao.java b/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/BundleSqlDao.java
index 3470b74..8ce78bb 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/BundleSqlDao.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/BundleSqlDao.java
@@ -41,7 +41,7 @@ import java.util.List;
 import java.util.UUID;
 
 @ExternalizedSqlViaStringTemplate3()
-public interface BundleSqlDao extends Transactional<EventSqlDao>, CloseMe, Transmogrifier {
+public interface BundleSqlDao extends Transactional<BundleSqlDao>, CloseMe, Transmogrifier {
 
     @SqlUpdate
     public void insertBundle(@Bind(binder = SubscriptionBundleBinder.class) SubscriptionBundleData bundle);
diff --git a/invoice/src/main/java/com/ning/billing/invoice/api/user/DefaultInvoiceCreationNotification.java b/invoice/src/main/java/com/ning/billing/invoice/api/user/DefaultInvoiceCreationNotification.java
new file mode 100644
index 0000000..094e6f1
--- /dev/null
+++ b/invoice/src/main/java/com/ning/billing/invoice/api/user/DefaultInvoiceCreationNotification.java
@@ -0,0 +1,64 @@
+/*
+ * 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.invoice.api.user;
+
+import java.math.BigDecimal;
+import java.util.UUID;
+import org.joda.time.DateTime;
+import com.ning.billing.catalog.api.Currency;
+import com.ning.billing.invoice.api.InvoiceCreationNotification;
+
+public class DefaultInvoiceCreationNotification implements InvoiceCreationNotification {
+    private final UUID invoiceId;
+    private final UUID accountId;
+    private final BigDecimal amountOwed;
+    private final Currency currency;
+    private final DateTime invoiceCreationDate;
+
+    public DefaultInvoiceCreationNotification(UUID invoiceId, UUID accountId, BigDecimal amountOwed, Currency currency, DateTime invoiceCreationDate) {
+        this.invoiceId = invoiceId;
+        this.accountId = accountId;
+        this.amountOwed = amountOwed;
+        this.currency = currency;
+        this.invoiceCreationDate = invoiceCreationDate;
+    }
+
+    @Override
+    public UUID getInvoiceId() {
+        return invoiceId;
+    }
+
+    @Override
+    public UUID getAccountId() {
+        return accountId;
+    }
+
+    @Override
+    public BigDecimal getAmountOwed() {
+        return amountOwed;
+    }
+
+    @Override
+    public Currency getCurrency() {
+        return currency;
+    }
+
+    @Override
+    public DateTime getInvoiceCreationDate() {
+        return invoiceCreationDate;
+    }
+}
diff --git a/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceDao.java b/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceDao.java
index f238b86..9beb139 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceDao.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceDao.java
@@ -20,6 +20,7 @@ import com.ning.billing.catalog.api.Currency;
 import com.ning.billing.invoice.api.Invoice;
 import com.ning.billing.invoice.api.InvoiceItem;
 import com.ning.billing.invoice.model.DefaultInvoice;
+import com.ning.billing.util.entity.EntityDao;
 import org.joda.time.DateTime;
 import org.skife.jdbi.v2.SQLStatement;
 import org.skife.jdbi.v2.StatementContext;
@@ -40,15 +41,13 @@ import java.util.UUID;
 
 @ExternalizedSqlViaStringTemplate3()
 @RegisterMapper({UuidMapper.class, InvoiceDao.InvoiceMapper.class})
-public interface InvoiceDao {
-    @SqlQuery
-    List<Invoice> getInvoicesByAccount(@Bind("accountId") final String accountId);
+public interface InvoiceDao extends EntityDao<Invoice> {
+    @Override
+    @SqlUpdate
+    void save(@InvoiceBinder Invoice invoice);
 
     @SqlQuery
-    Invoice getInvoice(@Bind("id") final String invoiceId);
-
-    @SqlUpdate
-    void createInvoice(@InvoiceBinder final Invoice invoice);
+    List<Invoice> getInvoicesByAccount(@Bind("accountId") final String accountId);
 
     @SqlQuery
     List<Invoice> getInvoicesBySubscription(@Bind("subscriptionId") final String subscriptionId);
@@ -66,9 +65,6 @@ public interface InvoiceDao {
     void notifyFailedPayment(@Bind("id") final String invoiceId,
                              @Bind("paymentAttemptDate") final Date paymentAttemptDate);
 
-    @SqlUpdate
-    void test();
-
     @BindingAnnotation(InvoiceBinder.InvoiceBinderFactory.class)
     @Retention(RetentionPolicy.RUNTIME)
     @Target({ElementType.PARAMETER})
diff --git a/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceDaoWrapper.java b/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceDaoWrapper.java
index 99a4a35..826d4ba 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceDaoWrapper.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceDaoWrapper.java
@@ -18,7 +18,16 @@ package com.ning.billing.invoice.dao;
 
 import com.google.inject.Inject;
 import com.ning.billing.invoice.api.Invoice;
+import com.ning.billing.invoice.api.InvoiceCreationNotification;
+import com.ning.billing.invoice.api.InvoiceItem;
+import com.ning.billing.invoice.api.user.DefaultInvoiceCreationNotification;
+import com.ning.billing.util.eventbus.EventBus;
+import org.skife.jdbi.v2.Handle;
 import org.skife.jdbi.v2.IDBI;
+import org.skife.jdbi.v2.TransactionCallback;
+import org.skife.jdbi.v2.TransactionStatus;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import java.math.BigDecimal;
 import java.util.Date;
@@ -26,50 +35,85 @@ import java.util.List;
 import java.util.UUID;
 
 public class InvoiceDaoWrapper implements InvoiceDao {
-    private final InvoiceDao dao;
+    private final IDBI dbi;
+
+    private final InvoiceDao invoiceDao;
+
+    private final EventBus eventBus;
+    private final static Logger log = LoggerFactory.getLogger(InvoiceDaoWrapper.class);
 
     @Inject
-    public InvoiceDaoWrapper(IDBI dbi) {
-        this.dao = dbi.onDemand(InvoiceDao.class);
+    public InvoiceDaoWrapper(IDBI dbi, EventBus eventBus) {
+        this.dbi = dbi;
+        this.invoiceDao = dbi.onDemand(InvoiceDao.class);
+        this.eventBus = eventBus;
     }
 
     @Override
     public List<Invoice> getInvoicesByAccount(final String accountId) {
-        return dao.getInvoicesByAccount(accountId);
+        return invoiceDao.getInvoicesByAccount(accountId);
+    }
+
+    @Override
+    public Invoice getById(final String invoiceId) {
+        return invoiceDao.getById(invoiceId);
     }
 
     @Override
-    public Invoice getInvoice(final String invoiceId) {
-        return dao.getInvoice(invoiceId);
+    public List<Invoice> get() {
+        return invoiceDao.get();
     }
 
     @Override
-    public void createInvoice(final Invoice invoice) {
-        dao.createInvoice(invoice);
+    public void save(final Invoice invoice) {
+         dbi.inTransaction(new TransactionCallback<Void>() {
+            @Override
+            public Void inTransaction(Handle conn, TransactionStatus status) throws Exception {
+                InvoiceDao invoiceDao = conn.attach(InvoiceDao.class);
+                Invoice currentInvoice = invoiceDao.getById(invoice.getId().toString());
+                invoiceDao.save(invoice);
+
+//                    List<InvoiceItem> invoiceItems = invoice.getItems();
+//                    InvoiceItemDao invoiceItemDao = conn.attach(InvoiceItemDao.class);
+//                    invoiceItemDao.save(invoiceItems);
+
+                if (currentInvoice == null) {
+                    InvoiceCreationNotification event;
+                    event = new DefaultInvoiceCreationNotification(invoice.getId(), invoice.getAccountId(),
+                                                                  invoice.getAmountOutstanding(), invoice.getCurrency(),
+                                                                  invoice.getInvoiceDate());
+                    eventBus.post(event);
+                } else {
+
+                }
+
+                return null;
+            }
+        });
     }
 
     @Override
     public List<Invoice> getInvoicesBySubscription(String subscriptionId) {
-        return dao.getInvoicesBySubscription(subscriptionId);
+        return invoiceDao.getInvoicesBySubscription(subscriptionId);
     }
 
     @Override
     public List<UUID> getInvoicesForPayment(Date targetDate, int numberOfDays) {
-        return dao.getInvoicesForPayment(targetDate, numberOfDays);
+        return invoiceDao.getInvoicesForPayment(targetDate, numberOfDays);
     }
 
     @Override
     public void notifySuccessfulPayment(String invoiceId, Date paymentDate, BigDecimal paymentAmount) {
-        dao.notifySuccessfulPayment(invoiceId, paymentDate, paymentAmount);
+        invoiceDao.notifySuccessfulPayment(invoiceId, paymentDate, paymentAmount);
     }
 
     @Override
     public void notifyFailedPayment(String invoiceId, Date paymentAttemptDate) {
-        dao.notifyFailedPayment(invoiceId, paymentAttemptDate);
+        invoiceDao.notifyFailedPayment(invoiceId, paymentAttemptDate);
     }
 
     @Override
     public void test() {
-        dao.test();
+        invoiceDao.test();
     }
 }
diff --git a/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceItemDao.java b/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceItemDao.java
index 1bb41b3..e45e1a9 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceItemDao.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceItemDao.java
@@ -19,6 +19,7 @@ package com.ning.billing.invoice.dao;
 import com.ning.billing.catalog.api.Currency;
 import com.ning.billing.invoice.api.InvoiceItem;
 import com.ning.billing.invoice.model.DefaultInvoiceItem;
+import com.ning.billing.util.entity.EntityDao;
 import org.joda.time.DateTime;
 import org.skife.jdbi.v2.SQLStatement;
 import org.skife.jdbi.v2.StatementContext;
@@ -36,10 +37,7 @@ import java.util.UUID;
 
 @ExternalizedSqlViaStringTemplate3()
 @RegisterMapper(InvoiceItemDao.InvoiceItemMapper.class)
-public interface InvoiceItemDao {
-    @SqlQuery
-    InvoiceItem getInvoiceItem(@Bind("id") final String invoiceItemId);
-
+public interface InvoiceItemDao extends EntityDao<InvoiceItem> {
     @SqlQuery
     List<InvoiceItem> getInvoiceItemsByInvoice(@Bind("invoiceId") final String invoiceId);
 
@@ -49,11 +47,9 @@ public interface InvoiceItemDao {
     @SqlQuery
     List<InvoiceItem> getInvoiceItemsBySubscription(@Bind("subscriptionId") final String subscriptionId);
 
+    @Override
     @SqlUpdate
-    void createInvoiceItem(@InvoiceItemBinder final InvoiceItem invoiceItem);
-
-    @SqlUpdate
-    void test();
+    void save(@InvoiceItemBinder final InvoiceItem invoiceItem);
 
     @BindingAnnotation(InvoiceItemBinder.InvoiceItemBinderFactory.class)
     @Retention(RetentionPolicy.RUNTIME)
diff --git a/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceItemDaoWrapper.java b/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceItemDaoWrapper.java
index 276785e..6e260bc 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceItemDaoWrapper.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/dao/InvoiceItemDaoWrapper.java
@@ -31,8 +31,13 @@ public class InvoiceItemDaoWrapper implements InvoiceItemDao {
     }
 
     @Override
-    public InvoiceItem getInvoiceItem(String invoiceItemId) {
-        return dao.getInvoiceItem(invoiceItemId);
+    public InvoiceItem getById(String invoiceItemId) {
+        return dao.getById(invoiceItemId);
+    }
+
+    @Override
+    public List<InvoiceItem> get() {
+        return dao.get();
     }
 
     @Override
@@ -51,8 +56,8 @@ public class InvoiceItemDaoWrapper implements InvoiceItemDao {
     }
 
     @Override
-    public void createInvoiceItem(InvoiceItem invoiceItem) {
-        dao.createInvoiceItem(invoiceItem);
+    public void save(InvoiceItem invoiceItem) {
+        dao.save(invoiceItem);
     }
 
     @Override
diff --git a/invoice/src/main/java/com/ning/billing/invoice/glue/InvoiceModule.java b/invoice/src/main/java/com/ning/billing/invoice/glue/InvoiceModule.java
index 9318510..9b40875 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/glue/InvoiceModule.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/glue/InvoiceModule.java
@@ -17,7 +17,7 @@
 package com.ning.billing.invoice.glue;
 
 import com.google.inject.AbstractModule;
-import com.ning.billing.invoice.api.DefaultInvoiceUserApi;
+import com.ning.billing.invoice.api.user.DefaultInvoiceUserApi;
 import com.ning.billing.invoice.api.InvoiceUserApi;
 import com.ning.billing.invoice.dao.InvoiceDao;
 import com.ning.billing.invoice.dao.InvoiceDaoWrapper;
diff --git a/invoice/src/main/resources/com/ning/billing/invoice/dao/InvoiceDao.sql.stg b/invoice/src/main/resources/com/ning/billing/invoice/dao/InvoiceDao.sql.stg
index b22f792..1fee936 100644
--- a/invoice/src/main/resources/com/ning/billing/invoice/dao/InvoiceDao.sql.stg
+++ b/invoice/src/main/resources/com/ning/billing/invoice/dao/InvoiceDao.sql.stg
@@ -23,15 +23,18 @@ getInvoicesForPayment() ::= <<
   HAVING SUM(ii.amount) > (i.amount_paid);
 >>
 
-getInvoice() ::= <<
+getById() ::= <<
   SELECT id, account_id, invoice_date, target_date, currency, amount_paid, last_payment_attempt
   FROM invoices
   WHERE id = :id;
 >>
 
-createInvoice() ::= <<
+save() ::= <<
   INSERT INTO invoices(id, account_id, invoice_date, target_date, currency, amount_paid, last_payment_attempt)
-  VALUES (:id, :accountId, :invoiceDate, :targetDate, :currency, :amountPaid, :lastPaymentAttempt);
+  VALUES (:id, :accountId, :invoiceDate, :targetDate, :currency, :amountPaid, :lastPaymentAttempt)
+  ON DUPLICATE KEY UPDATE
+    invoice_date = :invoiceDate, target_date = :targetDate, currency = :currency,
+    amount_paid = :amountPaid, last_payment_attempt = :lastPaymentAttempt;
 >>
 
 notifySuccessfulPayment() ::= <<
diff --git a/invoice/src/main/resources/com/ning/billing/invoice/dao/InvoiceItemDao.sql.stg b/invoice/src/main/resources/com/ning/billing/invoice/dao/InvoiceItemDao.sql.stg
index ffd4cf9..490d075 100644
--- a/invoice/src/main/resources/com/ning/billing/invoice/dao/InvoiceItemDao.sql.stg
+++ b/invoice/src/main/resources/com/ning/billing/invoice/dao/InvoiceItemDao.sql.stg
@@ -1,6 +1,6 @@
 group InvoiceItemDao;
 
-getInvoiceItem() ::= <<
+getById() ::= <<
   SELECT id, invoice_id, subscription_id, start_date, end_date, description, amount, rate, currency
   FROM invoice_items
   WHERE id = :id;
@@ -25,9 +25,12 @@ getInvoiceItemsBySubscription() ::= <<
   WHERE subscription_id = :subscriptionId;
 >>
 
-createInvoiceItem() ::= <<
+save() ::= <<
   INSERT INTO invoice_items(id, invoice_id, subscription_id, start_date, end_date, description, amount, rate, currency)
   VALUES(:id, :invoiceId, :subscriptionId, :startDate, :endDate, :description, :amount, :rate, :currency)
+  ON DUPLICATE KEY UPDATE
+    start_date = :startDate, end_date = :endDate, description = :description,
+    amount = :amount, rate = :rate, currency = :currency''
 >>
 
 test() ::= <<
diff --git a/invoice/src/test/java/com/ning/billing/invoice/dao/InvoiceDaoTestBase.java b/invoice/src/test/java/com/ning/billing/invoice/dao/InvoiceDaoTestBase.java
new file mode 100644
index 0000000..5d31a5f
--- /dev/null
+++ b/invoice/src/test/java/com/ning/billing/invoice/dao/InvoiceDaoTestBase.java
@@ -0,0 +1,58 @@
+/*
+ * 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.invoice.dao;
+
+import java.io.IOException;
+import org.apache.commons.io.IOUtils;
+import org.testng.annotations.BeforeClass;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.Stage;
+import com.ning.billing.invoice.glue.InvoiceModuleMock;
+import com.ning.billing.util.eventbus.DefaultEventBusService;
+import com.ning.billing.util.eventbus.EventBusService;
+
+import static org.testng.Assert.fail;
+
+public abstract class InvoiceDaoTestBase {
+    protected InvoiceDao invoiceDao;
+    protected InvoiceItemDao invoiceItemDao;
+
+    @BeforeClass()
+    protected void setup() throws IOException {
+        // Health check test to make sure MySQL is setup properly
+        try {
+            InvoiceModuleMock module = new InvoiceModuleMock();
+            final String ddl = IOUtils.toString(InvoiceDaoWrapper.class.getResourceAsStream("/com/ning/billing/invoice/ddl.sql"));
+            module.createDb(ddl);
+
+            final Injector injector = Guice.createInjector(Stage.DEVELOPMENT, module);
+
+            invoiceDao = injector.getInstance(InvoiceDaoWrapper.class);
+            invoiceDao.test();
+
+            invoiceItemDao = injector.getInstance(InvoiceItemDao.class);
+            invoiceItemDao.test();
+
+            EventBusService busService = injector.getInstance(EventBusService.class);
+            ((DefaultEventBusService) busService).startBus();
+        }
+        catch (Throwable t) {
+            fail(t.toString());
+        }
+    }
+}
diff --git a/invoice/src/test/java/com/ning/billing/invoice/dao/InvoiceDaoTests.java b/invoice/src/test/java/com/ning/billing/invoice/dao/InvoiceDaoTests.java
index 0dd5d47..675bdeb 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/dao/InvoiceDaoTests.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/dao/InvoiceDaoTests.java
@@ -20,12 +20,13 @@ import com.google.inject.Guice;
 import com.google.inject.Injector;
 import com.google.inject.Stage;
 import com.ning.billing.catalog.api.Currency;
-import com.ning.billing.dbi.MysqlTestingHelper;
 import com.ning.billing.invoice.api.Invoice;
 import com.ning.billing.invoice.glue.InvoiceModuleMock;
 import com.ning.billing.invoice.model.DefaultInvoice;
 import com.ning.billing.invoice.model.DefaultInvoiceItem;
 import com.ning.billing.util.clock.DefaultClock;
+import com.ning.billing.util.eventbus.DefaultEventBusService;
+import com.ning.billing.util.eventbus.EventBusService;
 import org.apache.commons.io.IOUtils;
 import org.joda.time.DateTime;
 import org.testng.annotations.BeforeClass;
@@ -38,44 +39,19 @@ import java.util.UUID;
 
 import static org.testng.Assert.*;
 
-@Test(groups = {"invoicing", "invoicing-dao"})
-public class InvoiceDaoTests {
+@Test(groups = {"invoicing", "invoicing-invoiceDao"})
+public class InvoiceDaoTests extends InvoiceDaoTestBase {
     private final int NUMBER_OF_DAY_BETWEEN_RETRIES = 8;
 
-    private final MysqlTestingHelper helper = new MysqlTestingHelper();
-    private InvoiceDao dao;
-    private InvoiceItemDao invoiceItemDao;
-
-    @BeforeClass()
-    private void setup() throws IOException {
-        // Health check test to make sure MySQL is setup properly
-        try {
-            InvoiceModuleMock module = new InvoiceModuleMock();
-            final String ddl = IOUtils.toString(InvoiceDaoWrapper.class.getResourceAsStream("/com/ning/billing/invoice/ddl.sql"));
-            module.createDb(ddl);
-
-            final Injector injector = Guice.createInjector(Stage.DEVELOPMENT, module);
-
-            dao = injector.getInstance(InvoiceDaoWrapper.class);
-            dao.test();
-
-            invoiceItemDao = injector.getInstance(InvoiceItemDao.class);
-            invoiceItemDao.test();
-        }
-        catch (Throwable t) {
-            fail(t.toString());
-        }
-    }
-
     @Test
     public void testCreationAndRetrievalByAccount() {
         UUID accountId = UUID.randomUUID();
         Invoice invoice = new DefaultInvoice(accountId, new DefaultClock().getUTCNow(), Currency.USD);
         DateTime invoiceDate = invoice.getInvoiceDate();
 
-        dao.createInvoice(invoice);
+        invoiceDao.save(invoice);
 
-        List<Invoice> invoices = dao.getInvoicesByAccount(accountId.toString());
+        List<Invoice> invoices = invoiceDao.getInvoicesByAccount(accountId.toString());
         assertNotNull(invoices);
         assertEquals(invoices.size(), 1);
         Invoice thisInvoice = invoices.get(0);
@@ -88,7 +64,7 @@ public class InvoiceDaoTests {
 
     @Test
     public void testRetrievalForNonExistentInvoiceId() {
-        Invoice invoice = dao.getInvoice(UUID.randomUUID().toString());
+        Invoice invoice = invoiceDao.getById(UUID.randomUUID().toString());
         assertNull(invoice);
     }
 
@@ -101,10 +77,10 @@ public class InvoiceDaoTests {
         DateTime paymentAttemptDate = new DateTime(2011, 6, 24, 12, 14, 36, 0);
         BigDecimal paymentAmount = new BigDecimal("14.0");
 
-        dao.createInvoice(invoice);
-        dao.notifySuccessfulPayment(invoice.getId().toString(), paymentAttemptDate.toDate(), paymentAmount);
+        invoiceDao.save(invoice);
+        invoiceDao.notifySuccessfulPayment(invoice.getId().toString(), paymentAttemptDate.toDate(), paymentAmount);
 
-        invoice = dao.getInvoice(invoice.getId().toString());
+        invoice = invoiceDao.getById(invoice.getId().toString());
         assertEquals(invoice.getAmountPaid().compareTo(paymentAmount), 0);
         assertTrue(invoice.getLastPaymentAttempt().equals(paymentAttemptDate));
     }
@@ -117,10 +93,10 @@ public class InvoiceDaoTests {
 
         DateTime paymentAttemptDate = new DateTime(2011, 6, 24, 12, 14, 36, 0);
 
-        dao.createInvoice(invoice);
-        dao.notifyFailedPayment(invoice.getId().toString(), paymentAttemptDate.toDate());
+        invoiceDao.save(invoice);
+        invoiceDao.notifyFailedPayment(invoice.getId().toString(), paymentAttemptDate.toDate());
 
-        invoice = dao.getInvoice(invoice.getId().toString());
+        invoice = invoiceDao.getById(invoice.getId().toString());
         assertTrue(invoice.getLastPaymentAttempt().equals(paymentAttemptDate));
     }
 
@@ -130,32 +106,31 @@ public class InvoiceDaoTests {
         DateTime targetDate = new DateTime(2011, 10, 6, 0, 0, 0, 0);
         
         // determine the number of existing invoices available for payment (to avoid side effects from other tests)
-        List<UUID> invoices = dao.getInvoicesForPayment(notionalDate.toDate(), NUMBER_OF_DAY_BETWEEN_RETRIES);
+        List<UUID> invoices = invoiceDao.getInvoicesForPayment(notionalDate.toDate(), NUMBER_OF_DAY_BETWEEN_RETRIES);
         int existingInvoiceCount = invoices.size();
         
         UUID accountId = UUID.randomUUID();
         Invoice invoice = new DefaultInvoice(accountId, targetDate, Currency.USD);
 
-        dao.createInvoice(invoice);
-        invoices = dao.getInvoicesForPayment(notionalDate.toDate(), NUMBER_OF_DAY_BETWEEN_RETRIES);
+        invoiceDao.save(invoice);
+        invoices = invoiceDao.getInvoicesForPayment(notionalDate.toDate(), NUMBER_OF_DAY_BETWEEN_RETRIES);
         assertEquals(invoices.size(), existingInvoiceCount);
     }
 
-    // TODO: test invoices for payment with results
     @Test
     public void testGetInvoicesForPayment() {
         List<UUID> invoices;
         DateTime notionalDate = new DateTime();
 
         // determine the number of existing invoices available for payment (to avoid side effects from other tests)
-        invoices = dao.getInvoicesForPayment(notionalDate.toDate(), NUMBER_OF_DAY_BETWEEN_RETRIES);
+        invoices = invoiceDao.getInvoicesForPayment(notionalDate.toDate(), NUMBER_OF_DAY_BETWEEN_RETRIES);
         int existingInvoiceCount = invoices.size();
 
         // create a new invoice with one item
         UUID accountId = UUID.randomUUID();
         DateTime targetDate = new DateTime(2011, 10, 6, 0, 0, 0, 0);
         Invoice invoice = new DefaultInvoice(accountId, targetDate, Currency.USD);
-        dao.createInvoice(invoice);
+        invoiceDao.save(invoice);
 
         UUID invoiceId = invoice.getId();
         UUID subscriptionId = UUID.randomUUID();
@@ -164,48 +139,48 @@ public class InvoiceDaoTests {
         BigDecimal amount = rate.multiply(new BigDecimal("3.0"));
 
         DefaultInvoiceItem item = new DefaultInvoiceItem(invoiceId, subscriptionId, targetDate, endDate, "test", amount, rate, Currency.USD);
-        invoiceItemDao.createInvoiceItem(item);
+        invoiceItemDao.save(item);
 
         // ensure that the number of invoices for payment has increased by 1
-        invoices = dao.getInvoicesForPayment(notionalDate.toDate(), NUMBER_OF_DAY_BETWEEN_RETRIES);
+        invoices = invoiceDao.getInvoicesForPayment(notionalDate.toDate(), NUMBER_OF_DAY_BETWEEN_RETRIES);
         assertEquals(invoices.size(), existingInvoiceCount + 1);
 
         // attempt a payment; ensure that the number of invoices for payment has decreased by 1 (no retries for eight days)
-        dao.notifyFailedPayment(invoice.getId().toString(), notionalDate.toDate());
-        invoices = dao.getInvoicesForPayment(notionalDate.toDate(), NUMBER_OF_DAY_BETWEEN_RETRIES);
+        invoiceDao.notifyFailedPayment(invoice.getId().toString(), notionalDate.toDate());
+        invoices = invoiceDao.getInvoicesForPayment(notionalDate.toDate(), NUMBER_OF_DAY_BETWEEN_RETRIES);
         assertEquals(invoices.size(), existingInvoiceCount);
 
         // advance clock by 8 days; ensure that number of invoices for payment has increased by 1 (retry)
         notionalDate = notionalDate.plusDays(NUMBER_OF_DAY_BETWEEN_RETRIES);
-        invoices = dao.getInvoicesForPayment(notionalDate.toDate(), NUMBER_OF_DAY_BETWEEN_RETRIES);
+        invoices = invoiceDao.getInvoicesForPayment(notionalDate.toDate(), NUMBER_OF_DAY_BETWEEN_RETRIES);
         assertEquals(invoices.size(), existingInvoiceCount + 1);
 
         // post successful partial payment; ensure that number of invoices for payment has decreased by 1
-        dao.notifySuccessfulPayment(invoiceId.toString(), notionalDate.toDate(), new BigDecimal("22.0000"));
-        invoices = dao.getInvoicesForPayment(notionalDate.toDate(), NUMBER_OF_DAY_BETWEEN_RETRIES);
+        invoiceDao.notifySuccessfulPayment(invoiceId.toString(), notionalDate.toDate(), new BigDecimal("22.0000"));
+        invoices = invoiceDao.getInvoicesForPayment(notionalDate.toDate(), NUMBER_OF_DAY_BETWEEN_RETRIES);
         assertEquals(invoices.size(), existingInvoiceCount);
 
         // get invoice; verify amount paid is correct
-        invoice = dao.getInvoice(invoiceId.toString());
+        invoice = invoiceDao.getById(invoiceId.toString());
         assertEquals(invoice.getAmountPaid().compareTo(new BigDecimal("22.0")), 0);
 
         // advance clock eight days; ensure that number of invoices for payment has increased by 1 (retry)
         notionalDate = notionalDate.plusDays(NUMBER_OF_DAY_BETWEEN_RETRIES);
-        invoices = dao.getInvoicesForPayment(notionalDate.toDate(), NUMBER_OF_DAY_BETWEEN_RETRIES);
+        invoices = invoiceDao.getInvoicesForPayment(notionalDate.toDate(), NUMBER_OF_DAY_BETWEEN_RETRIES);
         assertEquals(invoices.size(), existingInvoiceCount + 1);
 
         // post completed payment; ensure that the number of invoices for payment has decreased by 1
-        dao.notifySuccessfulPayment(invoiceId.toString(), notionalDate.toDate(), new BigDecimal("5.0000"));
-        invoices = dao.getInvoicesForPayment(notionalDate.toDate(), NUMBER_OF_DAY_BETWEEN_RETRIES);
+        invoiceDao.notifySuccessfulPayment(invoiceId.toString(), notionalDate.toDate(), new BigDecimal("5.0000"));
+        invoices = invoiceDao.getInvoicesForPayment(notionalDate.toDate(), NUMBER_OF_DAY_BETWEEN_RETRIES);
         assertEquals(invoices.size(), existingInvoiceCount);
 
         // get invoice; verify amount paid is correct
-        invoice = dao.getInvoice(invoiceId.toString());
+        invoice = invoiceDao.getById(invoiceId.toString());
         assertEquals(invoice.getAmountPaid().compareTo(new BigDecimal("27.0")), 0);
 
         // advance clock by 8 days; ensure that the number of invoices for payment hasn't changed
         notionalDate = notionalDate.plusDays(NUMBER_OF_DAY_BETWEEN_RETRIES);
-        invoices = dao.getInvoicesForPayment(notionalDate.toDate(), NUMBER_OF_DAY_BETWEEN_RETRIES);
+        invoices = invoiceDao.getInvoicesForPayment(notionalDate.toDate(), NUMBER_OF_DAY_BETWEEN_RETRIES);
         assertEquals(invoices.size(), existingInvoiceCount);
 
     }
@@ -224,7 +199,7 @@ public class InvoiceDaoTests {
 
         // create invoice 1 (subscriptions 1-4)
         Invoice invoice1 = new DefaultInvoice(accountId, targetDate, Currency.USD);
-        dao.createInvoice(invoice1);
+        invoiceDao.save(invoice1);
 
         UUID invoiceId1 = invoice1.getId();
 
@@ -232,20 +207,20 @@ public class InvoiceDaoTests {
         DateTime endDate = startDate.plusMonths(1);
 
         DefaultInvoiceItem item1 = new DefaultInvoiceItem(invoiceId1, subscriptionId1, startDate, endDate, "test A", rate1, rate1, Currency.USD);
-        invoiceItemDao.createInvoiceItem(item1);
+        invoiceItemDao.save(item1);
 
         DefaultInvoiceItem item2 = new DefaultInvoiceItem(invoiceId1, subscriptionId2, startDate, endDate, "test B", rate2, rate2, Currency.USD);
-        invoiceItemDao.createInvoiceItem(item2);
+        invoiceItemDao.save(item2);
 
         DefaultInvoiceItem item3 = new DefaultInvoiceItem(invoiceId1, subscriptionId3, startDate, endDate, "test C", rate3, rate3, Currency.USD);
-        invoiceItemDao.createInvoiceItem(item3);
+        invoiceItemDao.save(item3);
 
         DefaultInvoiceItem item4 = new DefaultInvoiceItem(invoiceId1, subscriptionId4, startDate, endDate, "test D", rate4, rate4, Currency.USD);
-        invoiceItemDao.createInvoiceItem(item4);
+        invoiceItemDao.save(item4);
 
         // create invoice 2 (subscriptions 1-3)
         DefaultInvoice invoice = new DefaultInvoice(accountId, targetDate, Currency.USD);
-        dao.createInvoice(invoice);
+        invoiceDao.save(invoice);
 
         UUID invoiceId2 = invoice.getId();
 
@@ -253,25 +228,25 @@ public class InvoiceDaoTests {
         endDate = startDate.plusMonths(1);
 
         DefaultInvoiceItem item5 = new DefaultInvoiceItem(invoiceId2, subscriptionId1, startDate, endDate, "test A", rate1, rate1, Currency.USD);
-        invoiceItemDao.createInvoiceItem(item5);
+        invoiceItemDao.save(item5);
 
         DefaultInvoiceItem item6 = new DefaultInvoiceItem(invoiceId2, subscriptionId2, startDate, endDate, "test B", rate2, rate2, Currency.USD);
-        invoiceItemDao.createInvoiceItem(item6);
+        invoiceItemDao.save(item6);
 
         DefaultInvoiceItem item7 = new DefaultInvoiceItem(invoiceId2, subscriptionId3, startDate, endDate, "test C", rate3, rate3, Currency.USD);
-        invoiceItemDao.createInvoiceItem(item7);
+        invoiceItemDao.save(item7);
 
         // check that each subscription returns the correct number of invoices
-        List<Invoice> items1 = dao.getInvoicesBySubscription(subscriptionId1.toString());
+        List<Invoice> items1 = invoiceDao.getInvoicesBySubscription(subscriptionId1.toString());
         assertEquals(items1.size(), 2);
 
-        List<Invoice> items2 = dao.getInvoicesBySubscription(subscriptionId2.toString());
+        List<Invoice> items2 = invoiceDao.getInvoicesBySubscription(subscriptionId2.toString());
         assertEquals(items2.size(), 2);
 
-        List<Invoice> items3 = dao.getInvoicesBySubscription(subscriptionId3.toString());
+        List<Invoice> items3 = invoiceDao.getInvoicesBySubscription(subscriptionId3.toString());
         assertEquals(items3.size(), 2);
 
-        List<Invoice> items4 = dao.getInvoicesBySubscription(subscriptionId4.toString());
+        List<Invoice> items4 = invoiceDao.getInvoicesBySubscription(subscriptionId4.toString());
         assertEquals(items4.size(), 1);
     }
     
diff --git a/invoice/src/test/java/com/ning/billing/invoice/dao/InvoiceItemDaoTests.java b/invoice/src/test/java/com/ning/billing/invoice/dao/InvoiceItemDaoTests.java
index 7e01ff2..0f30753 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/dao/InvoiceItemDaoTests.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/dao/InvoiceItemDaoTests.java
@@ -36,31 +36,7 @@ import java.util.UUID;
 
 import static org.testng.Assert.*;
 
-public class InvoiceItemDaoTests {
-    private InvoiceItemDaoWrapper dao;
-    private InvoiceDao invoiceDao;
-
-    @BeforeClass(alwaysRun = true)
-    private void setup() throws IOException {
-        InvoiceModuleMock module = new InvoiceModuleMock();
-        final String ddl = IOUtils.toString(InvoiceDaoWrapper.class.getResourceAsStream("/com/ning/billing/invoice/ddl.sql"));
-        module.createDb(ddl);
-
-        // Healthcheck test to make sure MySQL is setup properly
-        try {
-            final Injector injector = Guice.createInjector(Stage.DEVELOPMENT, module);
-
-            dao = injector.getInstance(InvoiceItemDaoWrapper.class);
-            dao.test();
-
-            invoiceDao = injector.getInstance(InvoiceDaoWrapper.class);
-            invoiceDao.test();
-        }
-        catch (Throwable t) {
-            fail(t.toString());
-        }
-    }
-
+public class InvoiceItemDaoTests extends InvoiceDaoTestBase {
     @Test
     public void testInvoiceItemCreation() {
         UUID invoiceId = UUID.randomUUID();
@@ -70,9 +46,9 @@ public class InvoiceItemDaoTests {
         BigDecimal rate = new BigDecimal("20.00");
 
         InvoiceItem item = new DefaultInvoiceItem(invoiceId, subscriptionId, startDate, endDate, "test", rate, rate, Currency.USD);
-        dao.createInvoiceItem(item);
+        invoiceItemDao.save(item);
 
-        InvoiceItem thisItem = dao.getInvoiceItem(item.getId().toString());
+        InvoiceItem thisItem = invoiceItemDao.getById(item.getId().toString());
         assertNotNull(thisItem);
         assertEquals(thisItem.getId(), item.getId());
         assertEquals(thisItem.getInvoiceId(), item.getInvoiceId());
@@ -94,10 +70,10 @@ public class InvoiceItemDaoTests {
         for (int i = 0; i < 3; i++) {
             UUID invoiceId = UUID.randomUUID();
             DefaultInvoiceItem item = new DefaultInvoiceItem(invoiceId, subscriptionId, startDate.plusMonths(i), startDate.plusMonths(i + 1), "test", rate, rate, Currency.USD);
-            dao.createInvoiceItem(item);
+            invoiceItemDao.save(item);
         }
 
-        List<InvoiceItem> items = dao.getInvoiceItemsBySubscription(subscriptionId.toString());
+        List<InvoiceItem> items = invoiceItemDao.getInvoiceItemsBySubscription(subscriptionId.toString());
         assertEquals(items.size(), 3);
     }
 
@@ -111,10 +87,10 @@ public class InvoiceItemDaoTests {
             UUID subscriptionId = UUID.randomUUID();
             BigDecimal amount = rate.multiply(new BigDecimal(i + 1));
             DefaultInvoiceItem item = new DefaultInvoiceItem(invoiceId, subscriptionId, startDate, startDate.plusMonths(1), "test", amount, amount, Currency.USD);
-            dao.createInvoiceItem(item);
+            invoiceItemDao.save(item);
         }
 
-        List<InvoiceItem> items = dao.getInvoiceItemsByInvoice(invoiceId.toString());
+        List<InvoiceItem> items = invoiceItemDao.getInvoiceItemsByInvoice(invoiceId.toString());
         assertEquals(items.size(), 5);
     }
 
@@ -124,7 +100,7 @@ public class InvoiceItemDaoTests {
         DateTime targetDate = new DateTime(2011, 5, 23, 0, 0, 0, 0);
         DefaultInvoice invoice = new DefaultInvoice(accountId, targetDate, Currency.USD);
 
-        invoiceDao.createInvoice(invoice);
+        invoiceDao.save(invoice);
 
         UUID invoiceId = invoice.getId();
         DateTime startDate = new DateTime(2011, 3, 1, 0, 0, 0, 0);
@@ -132,9 +108,9 @@ public class InvoiceItemDaoTests {
 
         UUID subscriptionId = UUID.randomUUID();
         DefaultInvoiceItem item = new DefaultInvoiceItem(invoiceId, subscriptionId, startDate, startDate.plusMonths(1), "test", rate, rate, Currency.USD);
-        dao.createInvoiceItem(item);
+        invoiceItemDao.save(item);
 
-        List<InvoiceItem> items = dao.getInvoiceItemsByAccount(accountId.toString());
+        List<InvoiceItem> items = invoiceItemDao.getInvoiceItemsByAccount(accountId.toString());
         assertEquals(items.size(), 1);
     }
 }
diff --git a/invoice/src/test/java/com/ning/billing/invoice/glue/InvoiceModuleMock.java b/invoice/src/test/java/com/ning/billing/invoice/glue/InvoiceModuleMock.java
index 7bccede..ba4114b 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/glue/InvoiceModuleMock.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/glue/InvoiceModuleMock.java
@@ -17,6 +17,7 @@
 package com.ning.billing.invoice.glue;
 
 import com.ning.billing.dbi.MysqlTestingHelper;
+import com.ning.billing.util.glue.EventBusModule;
 import org.skife.jdbi.v2.IDBI;
 
 import java.io.IOException;
@@ -33,5 +34,6 @@ public class InvoiceModuleMock extends InvoiceModule {
     public void configure() {
         bind(IDBI.class).toInstance(helper.getDBI());
         super.configure();
+        install(new EventBusModule());
     }
 }