killbill-memoizeit

TagStore persistence; dao cleanup

12/9/2011 2:08:41 PM

Details

diff --git a/account/src/main/java/com/ning/billing/account/api/DefaultTag.java b/account/src/main/java/com/ning/billing/account/api/DefaultTag.java
index 764524f..2732048 100644
--- a/account/src/main/java/com/ning/billing/account/api/DefaultTag.java
+++ b/account/src/main/java/com/ning/billing/account/api/DefaultTag.java
@@ -38,6 +38,11 @@ public class DefaultTag extends EntityBase implements Tag {
         this.dateAdded = dateAdded;
     }
 
+    public DefaultTag(UUID id, TagDescription tagDescription, String addedBy, DateTime dateAdded) {
+        this(id, tagDescription.getId(), tagDescription.getName(), tagDescription.getProcessPayment(),
+                tagDescription.getGenerateInvoice(), addedBy, dateAdded);
+    }
+
     public DefaultTag(TagDescription tagDescription, String addedBy, DateTime dateAdded) {
         this(UUID.randomUUID(), tagDescription.getId(), tagDescription.getName(), tagDescription.getProcessPayment(),
                 tagDescription.getGenerateInvoice(), addedBy, dateAdded);
diff --git a/account/src/main/java/com/ning/billing/account/dao/AccountDaoWrapper.java b/account/src/main/java/com/ning/billing/account/dao/AccountDaoWrapper.java
index 1a6ed35..8bf8b66 100644
--- a/account/src/main/java/com/ning/billing/account/dao/AccountDaoWrapper.java
+++ b/account/src/main/java/com/ning/billing/account/dao/AccountDaoWrapper.java
@@ -35,8 +35,6 @@ import com.ning.billing.util.eventbus.EventBus;
 
 public class AccountDaoWrapper implements AccountDao {
     private final AccountDao accountDao;
-    private final FieldStoreDao fieldStoreDao;
-    private final TagStoreDao tagStoreDao;
     private final IDBI dbi; // needed for transaction support
     private final EventBus eventBus;
 
@@ -45,48 +43,80 @@ public class AccountDaoWrapper implements AccountDao {
         this.dbi = dbi;
         this.eventBus = eventBus;
         this.accountDao = dbi.onDemand(AccountDao.class);
-        this.fieldStoreDao = dbi.onDemand(FieldStoreDao.class);
-        this.tagStoreDao = dbi.onDemand(TagStoreDao.class);
     }
 
     @Override
-    public Account getAccountByKey(String key) {
-        Account account = accountDao.getAccountByKey(key);
-        if (account != null) {
-            loadFields(account);
-        }
-        return account;
-    }
+    public Account getAccountByKey(final String key) {
+        return dbi.inTransaction(new TransactionCallback<Account>() {
+            @Override
+            public Account inTransaction(Handle conn, TransactionStatus status) throws Exception {
+                try {
+                    conn.begin();
+                    Account account = accountDao.getAccountByKey(key);
 
-    @Override
-    public Account getById(String id) {
-        Account account = accountDao.getById(id);
+                    if (account != null) {
+                        FieldStoreDao fieldStoreDao = conn.attach(FieldStoreDao.class);
+                        List<CustomField> fields = fieldStoreDao.load(account.getId().toString(), account.getObjectName());
 
-        if (account != null) {
-            loadFields(account);
-            loadTags(account);
-        }
+                        account.getFields().clear();
+                        if (fields != null) {
+                            for (CustomField field : fields) {
+                                account.getFields().setValue(field.getName(), field.getValue());
+                            }
+                        }
 
-        return account;
-    }
+                        TagStoreDao tagStoreDao = conn.attach(TagStoreDao.class);
+                        List<Tag> tags = tagStoreDao.load(account.getId().toString(), account.getObjectName());
+                        account.clearTags();
 
-    private void loadFields(Account account) {
-        List<CustomField> fields = fieldStoreDao.load(account.getId().toString(), account.getObjectName());
-        account.getFields().clear();
-        if (fields != null) {
-            for (CustomField field : fields) {
-                account.getFields().setValue(field.getName(), field.getValue());
+                        if (tags != null) {
+                            account.addTags(tags);
+                        }
+                    }
+
+                    return account;
+                } catch (Throwable t) {
+                    return null;
+                }
             }
-        }
+        });
     }
 
-    private void loadTags(Account account) {
-        List<Tag> tags = tagStoreDao.load(account.getId().toString(), account.getObjectName());
+    @Override
+    public Account getById(final String id) {
+        return dbi.inTransaction(new TransactionCallback<Account>() {
+            @Override
+            public Account inTransaction(Handle conn, TransactionStatus status) throws Exception {
+                try {
+                    conn.begin();
+                    Account account = accountDao.getById(id);
+
+                    if (account != null) {
+                        FieldStoreDao fieldStoreDao = conn.attach(FieldStoreDao.class);
+                        List<CustomField> fields = fieldStoreDao.load(account.getId().toString(), account.getObjectName());
+
+                        account.getFields().clear();
+                        if (fields != null) {
+                            for (CustomField field : fields) {
+                                account.getFields().setValue(field.getName(), field.getValue());
+                            }
+                        }
+
+                        TagStoreDao tagStoreDao = conn.attach(TagStoreDao.class);
+                        List<Tag> tags = tagStoreDao.load(account.getId().toString(), account.getObjectName());
+                        account.clearTags();
 
-        if (tags != null) {
-            account.clearTags();
-            account.addTags(tags);
-        }
+                        if (tags != null) {
+                            account.addTags(tags);
+                        }
+                    }
+
+                    return account;
+                } catch (Throwable t) {
+                    return null;
+                }
+            }
+        });
     }
 
     @Override
diff --git a/account/src/main/java/com/ning/billing/account/dao/FieldStoreDao.java b/account/src/main/java/com/ning/billing/account/dao/FieldStoreDao.java
index a4042b6..fa3e8e5 100644
--- a/account/src/main/java/com/ning/billing/account/dao/FieldStoreDao.java
+++ b/account/src/main/java/com/ning/billing/account/dao/FieldStoreDao.java
@@ -31,6 +31,8 @@ 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.SqlBatch;
+import org.skife.jdbi.v2.sqlobject.SqlQuery;
 import org.skife.jdbi.v2.sqlobject.customizers.RegisterMapper;
 import org.skife.jdbi.v2.sqlobject.stringtemplate.ExternalizedSqlViaStringTemplate3;
 import org.skife.jdbi.v2.tweak.ResultSetMapper;
@@ -41,6 +43,7 @@ import com.ning.billing.account.api.StringCustomField;
 @RegisterMapper(FieldStoreDao.CustomFieldMapper.class)
 public interface FieldStoreDao extends EntityCollectionDao<CustomField> {
     @Override
+    @SqlBatch
     public void save(@Bind("objectId") final String objectId,
                      @Bind("objectType") final String objectType,
                      @CustomFieldBinder final List<CustomField> entities);
diff --git a/account/src/main/java/com/ning/billing/account/dao/TagDescriptionDao.java b/account/src/main/java/com/ning/billing/account/dao/TagDescriptionDao.java
index 4238192..2b361ff 100644
--- a/account/src/main/java/com/ning/billing/account/dao/TagDescriptionDao.java
+++ b/account/src/main/java/com/ning/billing/account/dao/TagDescriptionDao.java
@@ -16,9 +16,67 @@
 
 package com.ning.billing.account.dao;
 
+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;
+import com.ning.billing.account.api.DefaultTag;
+import com.ning.billing.account.api.DefaultTagDescription;
 import com.ning.billing.account.api.TagDescription;
+import org.joda.time.DateTime;
+import org.skife.jdbi.v2.SQLStatement;
+import org.skife.jdbi.v2.StatementContext;
+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.SqlUpdate;
+import org.skife.jdbi.v2.sqlobject.customizers.RegisterMapper;
 import org.skife.jdbi.v2.sqlobject.stringtemplate.ExternalizedSqlViaStringTemplate3;
+import org.skife.jdbi.v2.tweak.ResultSetMapper;
 
 @ExternalizedSqlViaStringTemplate3
+@RegisterMapper(TagDescriptionDao.TagDescriptionMapper.class)
 public interface TagDescriptionDao extends EntityDao<TagDescription> {
+    @Override
+    @SqlUpdate
+    public void save(@TagDescriptionBinder TagDescription entity);
+
+    public class TagDescriptionMapper implements ResultSetMapper<TagDescription> {
+        @Override
+        public TagDescription map(int index, ResultSet result, StatementContext context) throws SQLException {
+            UUID id = UUID.fromString(result.getString("id"));
+            String name = result.getString("name");
+            String description = result.getString("description");
+            boolean processPayment = result.getBoolean("process_payment");
+            boolean generateInvoice = result.getBoolean("generate_invoice");
+            String createdBy = result.getString("created_by");
+            DateTime creationDate = new DateTime(result.getTimestamp("creation_date"));
+            return new DefaultTagDescription(id, name, description, processPayment, generateInvoice, createdBy, creationDate);
+        }
+    }
+
+    @BindingAnnotation(TagDescriptionBinder.TagDescriptionBinderFactory.class)
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target({ElementType.PARAMETER})
+    public @interface TagDescriptionBinder {
+        public static class TagDescriptionBinderFactory implements BinderFactory {
+            public Binder build(Annotation annotation) {
+                return new Binder<TagDescriptionBinder, TagDescription>() {
+                    public void bind(SQLStatement q, TagDescriptionBinder bind, TagDescription tagDescription) {
+                        q.bind("id", tagDescription.getId().toString());
+                        q.bind("name", tagDescription.getName());
+                        q.bind("createdBy", tagDescription.getCreatedBy());
+                        q.bind("creationDate", tagDescription.getCreationDate().toDate());
+                        q.bind("description", tagDescription.getDescription());
+                        q.bind("generateInvoice", tagDescription.getGenerateInvoice());
+                        q.bind("processPayment", tagDescription.getProcessPayment());
+                    }
+                };
+            }
+        }
+    }
 }
\ No newline at end of file
diff --git a/account/src/main/java/com/ning/billing/account/dao/TagStoreDao.java b/account/src/main/java/com/ning/billing/account/dao/TagStoreDao.java
index ea1ee98..ce51954 100644
--- a/account/src/main/java/com/ning/billing/account/dao/TagStoreDao.java
+++ b/account/src/main/java/com/ning/billing/account/dao/TagStoreDao.java
@@ -21,8 +21,13 @@ 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.List;
+import java.util.UUID;
+import org.joda.time.DateTime;
 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;
@@ -30,11 +35,14 @@ import org.skife.jdbi.v2.sqlobject.BindingAnnotation;
 import org.skife.jdbi.v2.sqlobject.SqlBatch;
 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.account.api.DefaultTag;
+import com.ning.billing.account.api.DefaultTagDescription;
 import com.ning.billing.account.api.Tag;
+import com.ning.billing.account.api.TagDescription;
 
 @ExternalizedSqlViaStringTemplate3
-@RegisterMapper(TagDescriptionMapper.class)
+@RegisterMapper(TagStoreDao.TagMapper.class)
 public interface TagStoreDao extends EntityCollectionDao<Tag> {
     @Override
     @SqlBatch
@@ -42,14 +50,33 @@ public interface TagStoreDao extends EntityCollectionDao<Tag> {
                      @Bind("objectType") final String objectType,
                      @TagBinder final List<Tag> entities);
 
+    public class TagMapper implements ResultSetMapper<Tag> {
+        @Override
+        public Tag map(int index, ResultSet result, StatementContext context) throws SQLException {
+            UUID tagDescriptionId = UUID.fromString(result.getString("tag_description_id"));
+            String name = result.getString("tag_description_name");
+            String description = result.getString("tag_description");
+            boolean processPayment = result.getBoolean("process_payment");
+            boolean generateInvoice = result.getBoolean("generate_invoice");
+            String createdBy = result.getString("created_by");
+            DateTime creationDate = new DateTime(result.getDate("creation_date"));
+            TagDescription tagDescription = new DefaultTagDescription(tagDescriptionId, name, description, processPayment, generateInvoice, createdBy, creationDate);
+
+            UUID id = UUID.fromString(result.getString("id"));
+            String addedBy = result.getString("added_by");
+            DateTime dateAdded = new DateTime(result.getTimestamp("date_added"));
+            return new DefaultTag(id, tagDescription, addedBy, dateAdded);
+        }
+    }
+
     @BindingAnnotation(TagBinder.TagBinderFactory.class)
     @Retention(RetentionPolicy.RUNTIME)
     @Target({ElementType.PARAMETER})
     public @interface TagBinder {
         public static class TagBinderFactory implements BinderFactory {
             public Binder build(Annotation annotation) {
-                return new Binder<TagBinder, DefaultTag>() {
-                    public void bind(SQLStatement q, TagBinder bind, DefaultTag tag) {
+                return new Binder<TagBinder, Tag>() {
+                    public void bind(SQLStatement q, TagBinder bind, Tag tag) {
                         q.bind("id", tag.getId().toString());
                         q.bind("tagDescriptionId", tag.getTagDescriptionId().toString());
                         q.bind("dateAdded", tag.getDateAdded().toDate());
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 dc551c2..5c191c2 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
@@ -18,10 +18,13 @@ package com.ning.billing.account.glue;
 
 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 org.skife.config.ConfigurationObjectFactory;
 
 public class AccountModule extends AbstractModule {
@@ -41,12 +44,16 @@ public class AccountModule extends AbstractModule {
     }
 
     private void installAccountUserApi() {
-        bind(AccountUserApi.class).to(com.ning.billing.account.api.user.AccountUserApi.class).asEagerSingleton();
+        bind(AccountUserApi.class).to(DefaultAccountUserApi.class).asEagerSingleton();
     }
 
-    private void installFieldStore() {
-        bind(FieldStoreDao.class).to(FieldStoreDaoWrapper.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() {
@@ -54,6 +61,7 @@ public class AccountModule extends AbstractModule {
         installAccountCore();
         installAccountDao();
         installAccountUserApi();
-        installFieldStore();
+//        installFieldStore();
+//        installTagStore();
     }
 }
diff --git a/account/src/main/resources/com/ning/billing/account/dao/FieldStoreDao.sql.stg b/account/src/main/resources/com/ning/billing/account/dao/FieldStoreDao.sql.stg
index 1e8c4c3..c995694 100644
--- a/account/src/main/resources/com/ning/billing/account/dao/FieldStoreDao.sql.stg
+++ b/account/src/main/resources/com/ning/billing/account/dao/FieldStoreDao.sql.stg
@@ -2,9 +2,9 @@ group IFieldStoreDao;
 
 save() ::= <<
   INSERT INTO custom_fields(id, object_id, object_type, field_name, field_value)
-  VALUES (:idAsString, :objectId, :objectType, :name, :value)
+  VALUES (:id, :objectId, :objectType, :fieldName, :fieldValue)
   ON DUPLICATE KEY UPDATE
-    field_value = :value;
+    field_value = :fieldValue;
 >>
 
 load() ::= <<
diff --git a/account/src/main/resources/com/ning/billing/account/dao/TagDescriptionDao.sql.stg b/account/src/main/resources/com/ning/billing/account/dao/TagDescriptionDao.sql.stg
index 7881bbf..bdde261 100644
--- a/account/src/main/resources/com/ning/billing/account/dao/TagDescriptionDao.sql.stg
+++ b/account/src/main/resources/com/ning/billing/account/dao/TagDescriptionDao.sql.stg
@@ -1,20 +1,16 @@
 group TagDescriptionDao;
 
-create() ::= <<
-  INSERT INTO tag_descriptions(id, name, added_by, created, description, generate_invoice, process_payment)
-  VALUES(:id, :name, :addedBy, :created, :description, :generateInvoice, :processPayment)
->>
-
-update() ::= <<
-  UPDATE tag_descriptions
-  SET name = :name, added_by = :addedBy, created :=created,
-      description := description, generateInvoice = :generateInvoice,
-      processPayment = :processPayment
-  WHERE id = :id;
+save() ::= <<
+  INSERT INTO tag_descriptions(id, name, created_by, creation_date, description, generate_invoice, process_payment)
+  VALUES(:id, :name, :createdBy, :creationDate, :description, :generateInvoice, :processPayment)
+  ON DUPLICATE KEY UPDATE
+    name = :name, created_by = :createdBy, creation_date = :creationDate,
+    description := description, generate_invoice = :generateInvoice,
+    process_payment = :processPayment
 >>
 
 load() ::= <<
-  SELECT id, name, added_by, created, description, generate_invoice, process_payment
+  SELECT id, name, created_by, creation_date, description, generate_invoice, process_payment
   FROM tag_descriptions
   WHERE id = :id;
 >>
diff --git a/account/src/main/resources/com/ning/billing/account/dao/TagStoreDao.sql.stg b/account/src/main/resources/com/ning/billing/account/dao/TagStoreDao.sql.stg
index 8520d6c..3b53b2e 100644
--- a/account/src/main/resources/com/ning/billing/account/dao/TagStoreDao.sql.stg
+++ b/account/src/main/resources/com/ning/billing/account/dao/TagStoreDao.sql.stg
@@ -9,9 +9,12 @@ save() ::= <<
 >>
 
 load() ::= <<
-    SELECT id, tag_description_id, object_id, object_type, date_added, added_by
-    FROM tags
-    WHERE object_id = :objectId AND object_type = :objectType;
+    SELECT t.id, t.tag_description_id, t.object_id, t.object_type, t.date_added, t.added_by,
+           td.name AS tag_description_name, td.description AS tag_description, td.process_payment, td.generate_invoice,
+           td.created_by, td.creation_date
+    FROM tags t
+    INNER JOIN tag_descriptions td ON t.tag_description_id = td.id
+    WHERE t.object_id = :objectId AND t.object_type = :objectType;
 >>
 
 test() ::= <<
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 f925467..9975918 100644
--- a/account/src/main/resources/com/ning/billing/account/ddl.sql
+++ b/account/src/main/resources/com/ning/billing/account/ddl.sql
@@ -29,11 +29,11 @@ DROP TABLE IF EXISTS tag_descriptions;
 CREATE TABLE tag_descriptions (
   id char(36) NOT NULL,
   name varchar(20) NOT NULL,
-  added_by varchar(50) NOT NULL,
-  created datetime NOT NULL,
+  created_by varchar(50) NOT NULL,
+  creation_date datetime NOT NULL,
   description varchar(200) NOT NULL,
-  generateInvoice boolean DEFAULT false,
-  processPayment boolean DEFAULT false,
+  generate_invoice boolean DEFAULT false,
+  process_payment boolean DEFAULT false,
   PRIMARY KEY(id)
 ) ENGINE=innodb;
 CREATE UNIQUE INDEX tag_descriptions_name ON tag_descriptions(name);
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 95b4ade..d191a0e 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
@@ -23,6 +23,7 @@ import com.ning.billing.account.glue.AccountModuleMock;
 import com.ning.billing.util.eventbus.DefaultEventBusService;
 import com.ning.billing.util.eventbus.EventBusService;
 import org.apache.commons.io.IOUtils;
+import org.skife.jdbi.v2.IDBI;
 import org.testng.annotations.BeforeClass;
 
 import java.io.IOException;
@@ -30,8 +31,9 @@ import java.io.IOException;
 import static org.testng.Assert.fail;
 
 public abstract class AccountDaoTestBase {
-    protected FieldStoreDao fieldStoreDao;
+    //protected FieldStoreDao fieldStoreDao;
     protected AccountDao accountDao;
+    protected IDBI dbi;
 
     @BeforeClass(alwaysRun = true)
     protected void setup() throws IOException {
@@ -43,8 +45,10 @@ public abstract class AccountDaoTestBase {
 
             final Injector injector = Guice.createInjector(Stage.DEVELOPMENT, module);
 
-            fieldStoreDao = injector.getInstance(FieldStoreDao.class);
-            fieldStoreDao.test();
+            //fieldStoreDao = injector.getInstance(FieldStoreDao.class);
+            //fieldStoreDao.test();
+
+            dbi = injector.getInstance(IDBI.class);
 
             accountDao = injector.getInstance(AccountDao.class);
             accountDao.test();
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 fa110ed..398df58 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
@@ -36,6 +36,7 @@ public class TestFieldStore extends AccountDaoTestBase {
         String fieldValue = "Kitty Hawk";
         fieldStore.setValue(fieldName, fieldValue);
 
+        FieldStoreDao fieldStoreDao = dbi.onDemand(FieldStoreDao.class);
         fieldStoreDao.save(id.toString(), objectType, fieldStore.getEntityList());
 
         fieldStore = DefaultFieldStore.create(id, objectType);
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 ed308ae..33b67d8 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
@@ -27,6 +27,7 @@ import com.ning.billing.account.api.Tag;
 import com.ning.billing.account.api.TagDescription;
 import com.ning.billing.account.api.user.AccountBuilder;
 import com.ning.billing.catalog.api.Currency;
+import com.ning.billing.util.clock.DefaultClock;
 
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertNotNull;
@@ -106,8 +107,11 @@ public class TestSimpleAccountDao extends AccountDaoTestBase {
     public void testTags() {
         Account account = createTestAccount();
         TagDescription description = new DefaultTagDescription("Test Tag", "For testing only", true, true, "Test System", new DateTime());
+        TagDescriptionDao tagDescriptionDao = dbi.onDemand(TagDescriptionDao.class);
+        tagDescriptionDao.save(description);
+
         String addedBy = "testTags()";
-        DateTime dateAdded = new DateTime();
+        DateTime dateAdded = new DefaultClock().getUTCNow();
         account.addTag(description, addedBy, dateAdded);
         assertEquals(account.getTagList().size(), 1);
         accountDao.save(account);
@@ -121,6 +125,6 @@ public class TestSimpleAccountDao extends AccountDaoTestBase {
         assertEquals(tag.getProcessPayment(), description.getProcessPayment());
         assertEquals(tag.getTagDescriptionId(), description.getId());
         assertEquals(tag.getAddedBy(), addedBy);
-        assertEquals(tag.getDateAdded(), dateAdded);
+        assertEquals(tag.getDateAdded().compareTo(dateAdded), 0);
     }
 }