killbill-memoizeit

util: make TagDao throw TagApiException, not InvoiceApiException Signed-off-by:

6/12/2012 11:30:19 PM

Details

diff --git a/account/src/test/java/com/ning/billing/account/dao/TestAccountDao.java b/account/src/test/java/com/ning/billing/account/dao/TestAccountDao.java
index e846a42..5e51ecd 100644
--- a/account/src/test/java/com/ning/billing/account/dao/TestAccountDao.java
+++ b/account/src/test/java/com/ning/billing/account/dao/TestAccountDao.java
@@ -28,6 +28,7 @@ import java.util.UUID;
 
 import com.ning.billing.account.api.AccountEmail;
 import com.ning.billing.account.api.DefaultAccountEmail;
+import com.ning.billing.util.api.TagApiException;
 import com.ning.billing.util.customfield.CustomField;
 import com.ning.billing.util.customfield.StringCustomField;
 import com.ning.billing.util.customfield.dao.AuditedCustomFieldDao;
@@ -146,7 +147,7 @@ public class TestAccountDao extends AccountDaoTestBase {
     }
 
     @Test
-    public void testTags() throws EntityPersistenceException {
+    public void testTags() throws EntityPersistenceException, TagApiException {
         Account account = createTestAccount(1);
         TagDefinition definition = new DefaultTagDefinition("Test Tag", "For testing only", false);
         TagDefinitionSqlDao tagDescriptionDao = dbi.onDemand(TagDefinitionSqlDao.class);
diff --git a/api/src/main/java/com/ning/billing/invoice/api/InvoiceUserApi.java b/api/src/main/java/com/ning/billing/invoice/api/InvoiceUserApi.java
index 56ee93f..1b8afb3 100644
--- a/api/src/main/java/com/ning/billing/invoice/api/InvoiceUserApi.java
+++ b/api/src/main/java/com/ning/billing/invoice/api/InvoiceUserApi.java
@@ -17,6 +17,7 @@
 package com.ning.billing.invoice.api;
 
 import com.ning.billing.catalog.api.Currency;
+import com.ning.billing.util.api.TagApiException;
 import com.ning.billing.util.callcontext.CallContext;
 import org.joda.time.DateTime;
 
@@ -40,9 +41,9 @@ public interface InvoiceUserApi {
     
     public Invoice triggerInvoiceGeneration(UUID accountId, DateTime targetDate, boolean dryRun, CallContext context) throws InvoiceApiException;
 
-    public void tagInvoiceAsWrittenOff(UUID invoiceId, CallContext context);
+    public void tagInvoiceAsWrittenOff(UUID invoiceId, CallContext context) throws TagApiException;
 
-    public void tagInvoiceAsNotWrittenOff(UUID invoiceId, CallContext context) throws InvoiceApiException;
+    public void tagInvoiceAsNotWrittenOff(UUID invoiceId, CallContext context) throws TagApiException;
 
     public InvoiceItem getCreditById(UUID creditId) throws InvoiceApiException;
 
diff --git a/api/src/main/java/com/ning/billing/util/api/TagApiException.java b/api/src/main/java/com/ning/billing/util/api/TagApiException.java
new file mode 100644
index 0000000..7b3c032
--- /dev/null
+++ b/api/src/main/java/com/ning/billing/util/api/TagApiException.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2010-2012 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.util.api;
+
+import com.ning.billing.BillingExceptionBase;
+import com.ning.billing.ErrorCode;
+
+public class TagApiException extends BillingExceptionBase {
+    private static final long serialVersionUID = 1L;
+
+    public TagApiException(final Throwable cause, final int code, final String msg) {
+        super(cause, code, msg);
+    }
+
+    public TagApiException(final Throwable cause, final ErrorCode code, final Object... args) {
+        super(cause, code, args);
+    }
+
+    public TagApiException(final ErrorCode code, final Object... args) {
+        super(code, args);
+    }
+}
diff --git a/api/src/main/java/com/ning/billing/util/api/TagDefinitionApiException.java b/api/src/main/java/com/ning/billing/util/api/TagDefinitionApiException.java
index a67f1ad..1b080d5 100644
--- a/api/src/main/java/com/ning/billing/util/api/TagDefinitionApiException.java
+++ b/api/src/main/java/com/ning/billing/util/api/TagDefinitionApiException.java
@@ -22,15 +22,15 @@ import com.ning.billing.ErrorCode;
 public class TagDefinitionApiException extends BillingExceptionBase {
     private static final long serialVersionUID = 1L;
 
-    public TagDefinitionApiException(Throwable cause, int code, final String msg) {
+    public TagDefinitionApiException(final Throwable cause, final int code, final String msg) {
         super(cause, code, msg);
     }
 
-    public TagDefinitionApiException(Throwable cause, ErrorCode code, final Object... args) {
+    public TagDefinitionApiException(final Throwable cause, final ErrorCode code, final Object... args) {
         super(cause, code, args);
     }
 
-    public TagDefinitionApiException(ErrorCode code, final Object... args) {
+    public TagDefinitionApiException(final ErrorCode code, final Object... args) {
         super(code, args);
     }
-}
\ No newline at end of file
+}
diff --git a/api/src/main/java/com/ning/billing/util/api/TagUserApi.java b/api/src/main/java/com/ning/billing/util/api/TagUserApi.java
index 2be6d6d..331cce4 100644
--- a/api/src/main/java/com/ning/billing/util/api/TagUserApi.java
+++ b/api/src/main/java/com/ning/billing/util/api/TagUserApi.java
@@ -54,13 +54,13 @@ public interface TagUserApi {
      */
     public TagDefinition getTagDefinition(String name) throws TagDefinitionApiException;
 
-    public void addTags(UUID objectId, ObjectType objectType, List<TagDefinition> tagDefinitions, CallContext context);
+    public void addTags(UUID objectId, ObjectType objectType, List<TagDefinition> tagDefinitions, CallContext context) throws TagApiException;
 
-    public void addTag(UUID objectId, ObjectType objectType, TagDefinition tagDefinition, CallContext context);
+    public void addTag(UUID objectId, ObjectType objectType, TagDefinition tagDefinition, CallContext context) throws TagApiException;
 
-    public void removeTags(UUID objectId, ObjectType objectType, List<TagDefinition> tagDefinitions, CallContext context);
+    public void removeTags(UUID objectId, ObjectType objectType, List<TagDefinition> tagDefinitions, CallContext context) throws TagApiException;
 
-    public void removeTag(UUID objectId, ObjectType objectType, TagDefinition tagDefinition, CallContext context);
+    public void removeTag(UUID objectId, ObjectType objectType, TagDefinition tagDefinition, CallContext context) throws TagApiException;
 
     public Map<String, Tag> getTags(UUID objectId, ObjectType objectType);
 }
diff --git a/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestIntegrationWithAutoInvoiceOffTag.java b/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestIntegrationWithAutoInvoiceOffTag.java
index 3b462f1..08ba27a 100644
--- a/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestIntegrationWithAutoInvoiceOffTag.java
+++ b/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestIntegrationWithAutoInvoiceOffTag.java
@@ -40,6 +40,7 @@ import com.ning.billing.entitlement.api.user.SubscriptionBundle;
 import com.ning.billing.entitlement.api.user.SubscriptionData;
 import com.ning.billing.invoice.api.Invoice;
 import com.ning.billing.invoice.api.InvoiceUserApi;
+import com.ning.billing.util.api.TagApiException;
 import com.ning.billing.util.api.TagDefinitionApiException;
 import com.ning.billing.util.api.TagUserApi;
 import com.ning.billing.util.dao.ObjectType;
@@ -166,7 +167,7 @@ public class TestIntegrationWithAutoInvoiceOffTag extends TestIntegrationBase {
     }
 
 
-    private void addTag(UUID id, ObjectType type) throws TagDefinitionApiException {
+    private void addTag(UUID id, ObjectType type) throws TagDefinitionApiException, TagApiException {
         TagDefinition def = tagApi.getTagDefinition(ControlTagType.AUTO_INVOICING_OFF.name());
         tagApi.addTag(id, type, def, context);
         Map<String,Tag> tags = tagApi.getTags(id, type);
diff --git a/invoice/src/main/java/com/ning/billing/invoice/api/user/DefaultInvoiceUserApi.java b/invoice/src/main/java/com/ning/billing/invoice/api/user/DefaultInvoiceUserApi.java
index 7f2ced3..7a231a4 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/api/user/DefaultInvoiceUserApi.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/api/user/DefaultInvoiceUserApi.java
@@ -22,6 +22,7 @@ import java.util.UUID;
 
 import com.ning.billing.catalog.api.Currency;
 import com.ning.billing.invoice.api.InvoiceItem;
+import com.ning.billing.util.api.TagApiException;
 import com.ning.billing.util.callcontext.CallContext;
 import org.joda.time.DateTime;
 
@@ -82,12 +83,12 @@ public class DefaultInvoiceUserApi implements InvoiceUserApi {
 	}
 
     @Override
-    public void tagInvoiceAsWrittenOff(final UUID invoiceId, final CallContext context) {
+    public void tagInvoiceAsWrittenOff(final UUID invoiceId, final CallContext context) throws TagApiException {
         dao.setWrittenOff(invoiceId, context);
     }
 
     @Override
-    public void tagInvoiceAsNotWrittenOff(final UUID invoiceId, final CallContext context) throws InvoiceApiException {
+    public void tagInvoiceAsNotWrittenOff(final UUID invoiceId, final CallContext context) throws TagApiException {
         dao.removeWrittenOff(invoiceId, context);
     }
 
diff --git a/invoice/src/main/java/com/ning/billing/invoice/dao/DefaultInvoiceDao.java b/invoice/src/main/java/com/ning/billing/invoice/dao/DefaultInvoiceDao.java
index c3bd916..b3145b5 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/dao/DefaultInvoiceDao.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/dao/DefaultInvoiceDao.java
@@ -39,6 +39,7 @@ import com.ning.billing.invoice.model.FixedPriceInvoiceItem;
 import com.ning.billing.invoice.model.RecurringInvoiceItem;
 import com.ning.billing.invoice.notification.NextBillingDatePoster;
 import com.ning.billing.util.ChangeType;
+import com.ning.billing.util.api.TagApiException;
 import com.ning.billing.util.api.TagUserApi;
 import com.ning.billing.util.callcontext.CallContext;
 import com.ning.billing.util.dao.EntityAudit;
@@ -260,12 +261,12 @@ public class DefaultInvoiceDao implements InvoiceDao {
     }
 
     @Override
-    public void setWrittenOff(final UUID invoiceId, final CallContext context) {
+    public void setWrittenOff(final UUID invoiceId, final CallContext context) throws TagApiException {
         tagUserApi.addTag(invoiceId, ObjectType.INVOICE, ControlTagType.WRITTEN_OFF.toTagDefinition(), context);
     }
 
     @Override
-    public void removeWrittenOff(final UUID invoiceId, final CallContext context) throws InvoiceApiException {
+    public void removeWrittenOff(final UUID invoiceId, final CallContext context) throws TagApiException {
         tagUserApi.removeTag(invoiceId, ObjectType.INVOICE, ControlTagType.WRITTEN_OFF.toTagDefinition(), context);
     }
 
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 c7e520b..20c3c53 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
@@ -21,6 +21,7 @@ import com.ning.billing.invoice.api.Invoice;
 import com.ning.billing.invoice.api.InvoiceApiException;
 import com.ning.billing.invoice.api.InvoiceItem;
 import com.ning.billing.invoice.api.InvoicePayment;
+import com.ning.billing.util.api.TagApiException;
 import com.ning.billing.util.callcontext.CallContext;
 import org.joda.time.DateTime;
 
@@ -55,9 +56,9 @@ public interface InvoiceDao {
 
 	List<Invoice> getAllInvoicesByAccount(final UUID accountId);
 
-    void setWrittenOff(final UUID invoiceId, final CallContext context);
+    void setWrittenOff(final UUID invoiceId, final CallContext context) throws TagApiException;
 
-    void removeWrittenOff(final UUID invoiceId, final CallContext context) throws InvoiceApiException;
+    void removeWrittenOff(final UUID invoiceId, final CallContext context) throws TagApiException;
 
     void postChargeback(final UUID invoicePaymentId, final BigDecimal amount, final CallContext context) throws InvoiceApiException;
 
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 e4ab210..a47a518 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
@@ -56,6 +56,7 @@ import com.ning.billing.invoice.model.RecurringInvoiceItem;
 import com.ning.billing.junction.api.BillingEventSet;
 import com.ning.billing.mock.BrainDeadProxyFactory;
 import com.ning.billing.mock.BrainDeadProxyFactory.ZombieControl;
+import com.ning.billing.util.api.TagApiException;
 import com.ning.billing.util.dao.ObjectType;
 import com.ning.billing.util.tag.ControlTagType;
 import com.ning.billing.util.tag.Tag;
@@ -632,7 +633,7 @@ public class InvoiceDaoTests extends InvoiceDaoTestBase {
     }
 
     @Test
-    public void testAddingWrittenOffTag() throws InvoiceApiException {
+    public void testAddingWrittenOffTag() throws InvoiceApiException, TagApiException {
         Subscription subscription = getZombieSubscription();
 
         Plan plan = BrainDeadProxyFactory.createBrainDeadProxyFor(Plan.class);
@@ -663,7 +664,7 @@ public class InvoiceDaoTests extends InvoiceDaoTestBase {
     }
 
     @Test
-    public void testRemoveWrittenOffTag() throws InvoiceApiException {
+    public void testRemoveWrittenOffTag() throws InvoiceApiException, TagApiException {
         Subscription subscription = getZombieSubscription();
 
         Plan plan = BrainDeadProxyFactory.createBrainDeadProxyFor(Plan.class);
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/JaxRsResourceBase.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/JaxRsResourceBase.java
index a302336..33d778c 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/JaxRsResourceBase.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/JaxRsResourceBase.java
@@ -23,6 +23,7 @@ import com.ning.billing.jaxrs.json.CustomFieldJson;
 import com.ning.billing.jaxrs.util.JaxrsUriBuilder;
 import com.ning.billing.jaxrs.util.TagHelper;
 import com.ning.billing.util.api.CustomFieldUserApi;
+import com.ning.billing.util.api.TagApiException;
 import com.ning.billing.util.api.TagDefinitionApiException;
 import com.ning.billing.util.api.TagUserApi;
 import com.ning.billing.util.callcontext.CallContext;
@@ -87,6 +88,8 @@ public abstract class JaxRsResourceBase implements JaxrsResource {
             return Response.status(Response.Status.BAD_REQUEST).entity(e.getMessage()).build();
         } catch (TagDefinitionApiException e) {
             return Response.status(Response.Status.BAD_REQUEST).entity(e.getMessage()).build();
+        } catch (TagApiException e) {
+            return Response.status(Response.Status.BAD_REQUEST).entity(e.getMessage()).build();
         }
     }
 
@@ -105,6 +108,8 @@ public abstract class JaxRsResourceBase implements JaxrsResource {
             return Response.status(Response.Status.BAD_REQUEST).entity(e.getMessage()).build();
         } catch (TagDefinitionApiException e) {
             return Response.status(Response.Status.BAD_REQUEST).entity(e.getMessage()).build();
+        } catch (TagApiException e) {
+            return Response.status(Response.Status.BAD_REQUEST).entity(e.getMessage()).build();
         }
     }
 
diff --git a/util/src/main/java/com/ning/billing/util/tag/api/DefaultTagUserApi.java b/util/src/main/java/com/ning/billing/util/tag/api/DefaultTagUserApi.java
index 93de7f8..1c812b0 100644
--- a/util/src/main/java/com/ning/billing/util/tag/api/DefaultTagUserApi.java
+++ b/util/src/main/java/com/ning/billing/util/tag/api/DefaultTagUserApi.java
@@ -21,6 +21,7 @@ import java.util.Map;
 import java.util.UUID;
 
 import com.google.inject.Inject;
+import com.ning.billing.util.api.TagApiException;
 import com.ning.billing.util.api.TagDefinitionApiException;
 import com.ning.billing.util.api.TagUserApi;
 import com.ning.billing.util.callcontext.CallContext;
@@ -62,22 +63,22 @@ public class DefaultTagUserApi implements TagUserApi {
     }
 
     @Override
-    public void addTags(final UUID objectId, final ObjectType objectType, final List<TagDefinition> tagDefinitions, final CallContext context) {
+    public void addTags(final UUID objectId, final ObjectType objectType, final List<TagDefinition> tagDefinitions, final CallContext context) throws TagApiException {
         tagDao.insertTags(objectId, objectType, tagDefinitions, context);
     }
 
     @Override
-    public void addTag(final UUID objectId, final ObjectType objectType, final TagDefinition tagDefinition, final CallContext context) {
+    public void addTag(final UUID objectId, final ObjectType objectType, final TagDefinition tagDefinition, final CallContext context) throws TagApiException {
         tagDao.insertTag(objectId, objectType, tagDefinition, context);
     }
 
     @Override
-    public void removeTag(final UUID objectId, final ObjectType objectType, final TagDefinition tagDefinition, final CallContext context) {
+    public void removeTag(final UUID objectId, final ObjectType objectType, final TagDefinition tagDefinition, final CallContext context) throws TagApiException {
         tagDao.deleteTag(objectId, objectType, tagDefinition, context);
     }
 
     @Override
-    public void removeTags(final UUID objectId, final ObjectType objectType, final List<TagDefinition> tagDefinitions, final CallContext context) {
+    public void removeTags(final UUID objectId, final ObjectType objectType, final List<TagDefinition> tagDefinitions, final CallContext context) throws TagApiException {
         // TODO: consider making this batch
         for (final TagDefinition tagDefinition : tagDefinitions) {
             tagDao.deleteTag(objectId, objectType, tagDefinition, context);
diff --git a/util/src/main/java/com/ning/billing/util/tag/dao/AuditedTagDao.java b/util/src/main/java/com/ning/billing/util/tag/dao/AuditedTagDao.java
index c34985f..6df6ca2 100644
--- a/util/src/main/java/com/ning/billing/util/tag/dao/AuditedTagDao.java
+++ b/util/src/main/java/com/ning/billing/util/tag/dao/AuditedTagDao.java
@@ -25,12 +25,14 @@ import java.util.UUID;
 import org.skife.jdbi.v2.IDBI;
 import org.skife.jdbi.v2.Transaction;
 import org.skife.jdbi.v2.TransactionStatus;
+import org.skife.jdbi.v2.exceptions.TransactionFailedException;
 import org.skife.jdbi.v2.sqlobject.mixins.Transmogrifier;
 
 import com.google.inject.Inject;
 import com.ning.billing.ErrorCode;
-import com.ning.billing.invoice.api.InvoiceApiException;
 import com.ning.billing.util.ChangeType;
+import com.ning.billing.util.api.TagApiException;
+import com.ning.billing.util.api.TagDefinitionApiException;
 import com.ning.billing.util.bus.Bus;
 import com.ning.billing.util.callcontext.CallContext;
 import com.ning.billing.util.dao.AuditedCollectionDaoBase;
@@ -114,40 +116,47 @@ public class AuditedTagDao extends AuditedCollectionDaoBase<Tag, Tag> implements
     }
 
     @Override
-    public void deleteTag(final UUID objectId, final ObjectType objectType,
-                          final TagDefinition tagDefinition, final CallContext context) {
-        tagSqlDao.inTransaction(new Transaction<Void, TagSqlDao>() {
-            @Override
-            public Void inTransaction(final TagSqlDao tagSqlDao, final TransactionStatus status) throws Exception {
-                final String tagName = tagDefinition.getName();
-                final Tag tag = tagSqlDao.findTag(tagName, objectId.toString(), objectType);
-
-                if (tag == null) {
-                    throw new InvoiceApiException(ErrorCode.TAG_DOES_NOT_EXIST, tagName);
+    public void deleteTag(final UUID objectId, final ObjectType objectType, final TagDefinition tagDefinition, final CallContext context) throws TagApiException {
+        try {
+            tagSqlDao.inTransaction(new Transaction<Void, TagSqlDao>() {
+                @Override
+                public Void inTransaction(final TagSqlDao tagSqlDao, final TransactionStatus status) throws Exception {
+                    // Make sure the tag exists
+                    final String tagName = tagDefinition.getName();
+                    final Tag tag = tagSqlDao.findTag(tagName, objectId.toString(), objectType);
+                    if (tag == null) {
+                        throw new TagApiException(ErrorCode.TAG_DOES_NOT_EXIST, tagName);
+                    }
+
+                    final List<Tag> tagList = Arrays.asList(tag);
+
+                    final List<Mapper<UUID, Long>> recordIds = tagSqlDao.getRecordIds(objectId.toString(), objectType);
+                    final Map<UUID, Long> recordIdMap = convertToHistoryMap(recordIds);
+
+                    tagSqlDao.deleteFromTransaction(objectId.toString(), objectType, tagList, context);
+
+                    final List<EntityHistory<Tag>> entityHistories = new ArrayList<EntityHistory<Tag>>();
+                    entityHistories.addAll(convertToHistory(tagList, recordIdMap, ChangeType.DELETE));
+
+                    final Long maxHistoryRecordId = tagSqlDao.getMaxHistoryRecordId();
+                    tagSqlDao.addHistoryFromTransaction(objectId.toString(), objectType, entityHistories, context);
+
+                    // have to fetch history record ids to update audit log
+                    final List<Mapper<Long, Long>> historyRecordIds = tagSqlDao.getHistoryRecordIds(maxHistoryRecordId);
+                    final Map<Long, Long> historyRecordIdMap = convertToAuditMap(historyRecordIds);
+                    final List<EntityAudit> entityAudits = convertToAudits(entityHistories, historyRecordIdMap);
+                    tagSqlDao.insertAuditFromTransaction(entityAudits, context);
+
+                    return null;
                 }
-
-                final List<Tag> tagList = Arrays.asList(tag);
-
-                final List<Mapper<UUID, Long>> recordIds = tagSqlDao.getRecordIds(objectId.toString(), objectType);
-                final Map<UUID, Long> recordIdMap = convertToHistoryMap(recordIds);
-
-                tagSqlDao.deleteFromTransaction(objectId.toString(), objectType, tagList, context);
-
-                final List<EntityHistory<Tag>> entityHistories = new ArrayList<EntityHistory<Tag>>();
-                entityHistories.addAll(convertToHistory(tagList, recordIdMap, ChangeType.DELETE));
-
-                final Long maxHistoryRecordId = tagSqlDao.getMaxHistoryRecordId();
-                tagSqlDao.addHistoryFromTransaction(objectId.toString(), objectType, entityHistories, context);
-
-                // have to fetch history record ids to update audit log
-                final List<Mapper<Long, Long>> historyRecordIds = tagSqlDao.getHistoryRecordIds(maxHistoryRecordId);
-                final Map<Long, Long> historyRecordIdMap = convertToAuditMap(historyRecordIds);
-                final List<EntityAudit> entityAudits = convertToAudits(entityHistories, historyRecordIdMap);
-                tagSqlDao.insertAuditFromTransaction(entityAudits, context);
-
-                return null;
+            });
+        } catch (TransactionFailedException exception) {
+            if (exception.getCause() instanceof TagDefinitionApiException) {
+                throw (TagApiException) exception.getCause();
+            } else {
+                throw exception;
             }
-        });
+        }
     }
 
     @Override
diff --git a/util/src/main/java/com/ning/billing/util/tag/dao/TagDao.java b/util/src/main/java/com/ning/billing/util/tag/dao/TagDao.java
index db059ce..7d0105c 100644
--- a/util/src/main/java/com/ning/billing/util/tag/dao/TagDao.java
+++ b/util/src/main/java/com/ning/billing/util/tag/dao/TagDao.java
@@ -19,6 +19,7 @@ package com.ning.billing.util.tag.dao;
 import java.util.List;
 import java.util.UUID;
 
+import com.ning.billing.util.api.TagApiException;
 import com.ning.billing.util.callcontext.CallContext;
 import com.ning.billing.util.dao.AuditedCollectionDao;
 import com.ning.billing.util.dao.ObjectType;
@@ -26,9 +27,9 @@ import com.ning.billing.util.tag.Tag;
 import com.ning.billing.util.tag.TagDefinition;
 
 public interface TagDao extends AuditedCollectionDao<Tag> {
-    void insertTag(UUID objectId, ObjectType objectType, TagDefinition tagDefinition, CallContext context);
+    void insertTag(UUID objectId, ObjectType objectType, TagDefinition tagDefinition, CallContext context) throws TagApiException;
 
-    void insertTags(UUID objectId, ObjectType objectType, List<TagDefinition> tagDefinitions, CallContext context);
+    void insertTags(UUID objectId, ObjectType objectType, List<TagDefinition> tagDefinitions, CallContext context) throws TagApiException;
 
-    void deleteTag(UUID objectId, ObjectType objectType, TagDefinition tagDefinition, CallContext context);
+    void deleteTag(UUID objectId, ObjectType objectType, TagDefinition tagDefinition, CallContext context) throws TagApiException;
 }
diff --git a/util/src/test/java/com/ning/billing/util/tag/TestTagStore.java b/util/src/test/java/com/ning/billing/util/tag/TestTagStore.java
index 8dcd638..69187ae 100644
--- a/util/src/test/java/com/ning/billing/util/tag/TestTagStore.java
+++ b/util/src/test/java/com/ning/billing/util/tag/TestTagStore.java
@@ -37,7 +37,7 @@ import org.testng.annotations.Test;
 
 import com.google.inject.Inject;
 import com.ning.billing.dbi.MysqlTestingHelper;
-import com.ning.billing.invoice.api.InvoiceApiException;
+import com.ning.billing.util.api.TagApiException;
 import com.ning.billing.util.api.TagDefinitionApiException;
 import com.ning.billing.util.bus.Bus;
 import com.ning.billing.util.callcontext.CallContext;
@@ -285,7 +285,7 @@ public class TestTagStore {
     }
 
     @Test(groups = "slow")
-    public void testDeleteTagBeforeDeleteTagDefinition() {
+    public void testDeleteTagBeforeDeleteTagDefinition() throws TagApiException {
         final String definitionName = "TestTag1234567";
         try {
             tagDefinitionDao.create(definitionName, "Some test tag", context);
@@ -342,7 +342,7 @@ public class TestTagStore {
 
         final Handle handle = dbi.open();
         final String query = String.format("select * from audit_log a inner join tag_history th on a.record_id = th.history_record_id where a.table_name = 'tag_history' and th.id='%s' and a.change_type='INSERT'",
-                                     tag.getId().toString());
+                                           tag.getId().toString());
         final List<Map<String, Object>> result = handle.select(query);
         handle.close();
 
@@ -373,7 +373,7 @@ public class TestTagStore {
 
         final Handle handle = dbi.open();
         final String query = String.format("select * from audit_log a inner join tag_history th on a.record_id = th.history_record_id where a.table_name = 'tag_history' and th.id='%s' and a.change_type='DELETE'",
-                                     tag.getId().toString());
+                                           tag.getId().toString());
         final List<Map<String, Object>> result = handle.select(query);
         handle.close();
 
@@ -386,7 +386,7 @@ public class TestTagStore {
     }
 
     @Test
-    public void testAddTag() {
+    public void testAddTag() throws TagApiException {
         final UUID objectId = UUID.randomUUID();
         final ObjectType objectType = ObjectType.INVOICE;
         final TagDefinition tagDefinition = new DefaultTagDefinition("test tag", "test", false);
@@ -396,7 +396,7 @@ public class TestTagStore {
     }
 
     @Test
-    public void testRemoveTag() throws InvoiceApiException {
+    public void testRemoveTag() throws TagApiException {
         final UUID objectId = UUID.randomUUID();
         final ObjectType objectType = ObjectType.INVOICE;
         final TagDefinition tagDefinition = new DefaultTagDefinition("test tag", "test", false);