killbill-aplcache

Changes

jaxrs/src/main/java/com/ning/billing/jaxrs/util/TagHelper.java 49(+0 -49)

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 06d4bb9..68e6796 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
@@ -157,12 +157,12 @@ public class TestAccountDao extends AccountDaoTestBase {
         tagDescriptionDao.create(definition, context);
 
         final TagDao tagDao = new AuditedTagDao(dbi, tagEventBuilder, bus);
-        tagDao.insertTag(account.getId(), ObjectType.ACCOUNT, definition, context);
+        tagDao.insertTag(account.getId(), ObjectType.ACCOUNT, definition.getId(), context);
 
         final Map<String, Tag> tagMap = tagDao.loadEntities(account.getId(), ObjectType.ACCOUNT);
         assertEquals(tagMap.size(), 1);
-        final Tag tag = tagMap.get(definition.getName());
-        assertEquals(tag.getTagDefinitionName(), definition.getName());
+
+        assertEquals(tagMap.values().iterator().next().getTagDefinitionId(), definition.getId());
     }
 
     @Test
diff --git a/api/src/main/java/com/ning/billing/ErrorCode.java b/api/src/main/java/com/ning/billing/ErrorCode.java
index 5f94c15..abfd899 100644
--- a/api/src/main/java/com/ning/billing/ErrorCode.java
+++ b/api/src/main/java/com/ning/billing/ErrorCode.java
@@ -159,12 +159,12 @@ public enum ErrorCode {
     * Range 3900: Tag definitions
     *
     */
-    TAG_DEFINITION_CONFLICTS_WITH_CONTROL_TAG(3900, "The tag definition name conflicts with a reserved name (name %s)"),
-    TAG_DEFINITION_ALREADY_EXISTS(3901, "The tag definition name already exists (name: %s)"),
-    TAG_DEFINITION_DOES_NOT_EXIST(3902, "The tag definition name does not exist (name: %s)"),
-    TAG_DEFINITION_IN_USE(3903, "The tag definition name is currently in use (name: %s)"),
+    TAG_DEFINITION_CONFLICTS_WITH_CONTROL_TAG(3900, "The tag definition name conflicts with a reserved %s"),
+    TAG_DEFINITION_ALREADY_EXISTS(3901, "The tag definition name already exists %s"),
+    TAG_DEFINITION_DOES_NOT_EXIST(3902, "The tag definition name does not exist %s"),
+    TAG_DEFINITION_IN_USE(3903, "The tag definition name is currently in use %s"),
 
-    CONTROL_TAG_DOES_NOT_EXIST(3904, "The control tag does not exist (name: %s)"),
+    CONTROL_TAG_DOES_NOT_EXIST(3904, "The control tag does not exist %s"),
 
     /*
     *
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 331cce4..5312fc4 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
@@ -16,6 +16,7 @@
 
 package com.ning.billing.util.api;
 
+import java.util.Collection;
 import java.util.List;
 import java.util.Map;
 import java.util.UUID;
@@ -41,26 +42,31 @@ public interface TagUserApi {
     public TagDefinition create(String definitionName, String description, CallContext context) throws TagDefinitionApiException;
 
     /**
-     * @param definitionName Identifies the definition.
+     * @param tagDefinitionId The UUID for that tagDefinition
      * @param context        The call context, for auditing purposes
      * @throws TagDefinitionApiException
      */
-    public void deleteTagDefinition(String definitionName, CallContext context) throws TagDefinitionApiException;
+    public void deleteTagDefinition(UUID tagDefinitionId, CallContext context) throws TagDefinitionApiException;
 
-    /**
-     * @param name
-     * @return the tag with this definition
-     * @throws TagDefinitionApiException
-     */
-    public TagDefinition getTagDefinition(String name) throws TagDefinitionApiException;
+    public TagDefinition getTagDefinition(UUID tagDefinitionId) throws TagDefinitionApiException;
 
-    public void addTags(UUID objectId, ObjectType objectType, List<TagDefinition> tagDefinitions, CallContext context) throws TagApiException;
+    public TagDefinition getTagDefinitionForName(String tageDefinitionName) throws TagDefinitionApiException;
 
-    public void addTag(UUID objectId, ObjectType objectType, TagDefinition tagDefinition, CallContext context) throws TagApiException;
+    public List<TagDefinition> getTagDefinitions(final Collection<UUID> tagDefinitionIds) throws TagDefinitionApiException;
 
-    public void removeTags(UUID objectId, ObjectType objectType, List<TagDefinition> tagDefinitions, CallContext context) throws TagApiException;
+    public void addTags(UUID objectId, ObjectType objectType, Collection<UUID> tagDefinitionIds, CallContext context) throws TagApiException;
 
-    public void removeTag(UUID objectId, ObjectType objectType, TagDefinition tagDefinition, CallContext context) throws TagApiException;
+    public void addTag(UUID objectId, ObjectType objectType, UUID tagDefinitionId, CallContext context) throws TagApiException;
 
+    public void removeTags(UUID objectId, ObjectType objectType, Collection<UUID> tagDefinitions, CallContext context) throws TagApiException;
+
+    public void removeTag(UUID objectId, ObjectType objectType, UUID tagDefinitionId, CallContext context) throws TagApiException;
+
+    /**
+     *
+     * @param objectId UUID of the object on which to retrieve the tags
+     * @param objectType The type of object
+     * @return A map of tag, key being the tagId, and value the tag
+     */
     public Map<String, Tag> getTags(UUID objectId, ObjectType objectType);
 }
diff --git a/api/src/main/java/com/ning/billing/util/tag/ControlTagType.java b/api/src/main/java/com/ning/billing/util/tag/ControlTagType.java
index 632da11..709f34b 100644
--- a/api/src/main/java/com/ning/billing/util/tag/ControlTagType.java
+++ b/api/src/main/java/com/ning/billing/util/tag/ControlTagType.java
@@ -19,6 +19,7 @@ package com.ning.billing.util.tag;
 import java.util.UUID;
 
 public enum ControlTagType {
+
     AUTO_PAY_OFF(new UUID(0, 1), "Suspends payments until removed.", true, false),
     AUTO_INVOICING_OFF(new UUID(0, 2), "Suspends invoicing until removed.", false, true),
     OVERDUE_ENFORCEMENT_OFF(new UUID(0, 3), "Suspends overdue enforcement behaviour until removed.", false, false),
@@ -51,28 +52,4 @@ public enum ControlTagType {
     public boolean getAutoInvoicingOff() {
         return this.autoInvoicingOff;
     }
-
-    public TagDefinition toTagDefinition() {
-        return new TagDefinition() {
-            @Override
-            public String getName() {
-                return name();
-            }
-
-            @Override
-            public String getDescription() {
-                return description;
-            }
-
-            @Override
-            public Boolean isControlTag() {
-                return true;
-            }
-
-            @Override
-            public UUID getId() {
-                return id;
-            }
-        };
-    }
 }
diff --git a/api/src/main/java/com/ning/billing/util/tag/Tag.java b/api/src/main/java/com/ning/billing/util/tag/Tag.java
index 0a592cf..553ef5f 100644
--- a/api/src/main/java/com/ning/billing/util/tag/Tag.java
+++ b/api/src/main/java/com/ning/billing/util/tag/Tag.java
@@ -16,8 +16,10 @@
 
 package com.ning.billing.util.tag;
 
+import java.util.UUID;
+
 import com.ning.billing.util.entity.Entity;
 
 public interface Tag extends Entity {
-    String getTagDefinitionName();
+    UUID getTagDefinitionId();
 }
diff --git a/beatrix/src/test/java/com/ning/billing/beatrix/integration/overdue/TestOverdueIntegration.java b/beatrix/src/test/java/com/ning/billing/beatrix/integration/overdue/TestOverdueIntegration.java
index 8709621..148fb04 100644
--- a/beatrix/src/test/java/com/ning/billing/beatrix/integration/overdue/TestOverdueIntegration.java
+++ b/beatrix/src/test/java/com/ning/billing/beatrix/integration/overdue/TestOverdueIntegration.java
@@ -187,12 +187,15 @@ public class TestOverdueIntegration extends TestIntegrationBase {
         // Clear databases
     }
 
+    // We set the the property killbill.payment.retry.days=100,100,100 so that Payment retry logics does not end with an ABORTED state
+    // preventing final instant payment to succeed.
+    //
     @Test(groups = {"slow"}, enabled = true)
     public void testBasicOverdueState() throws Exception {
         clock.setTime(new DateTime(2012, 5, 1, 0, 3, 42, 0));
         paymentPlugin.makeAllInvoicesFailWithError(true);
 
-        // set next invoice to fail and create subscription 
+        // set next invoice to fail and create subscription
         busHandler.pushExpectedEvents(NextEvent.CREATE, NextEvent.INVOICE);
         final SubscriptionData baseSubscription = subscriptionDataFromSubscription(entitlementUserApi.createSubscription(bundle.getId(),
                                                                                                                    new PlanPhaseSpecifier(productName, ProductCategory.BASE, term, planSetName, null), null, context));
diff --git a/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestAnalytics.java b/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestAnalytics.java
index 62e15e2..8a20602 100644
--- a/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestAnalytics.java
+++ b/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestAnalytics.java
@@ -388,7 +388,7 @@ public class TestAnalytics extends TestIntegrationBase {
         Assert.assertEquals(analyticsUserApi.getTagsForAccount(account.getExternalKey()).size(), 0);
 
         final TagDefinition tagDefinition = tagUserApi.create(UUID.randomUUID().toString().substring(0, 10), UUID.randomUUID().toString(), context);
-        tagUserApi.addTag(account.getId(), ObjectType.ACCOUNT, tagDefinition, context);
+        tagUserApi.addTag(account.getId(), ObjectType.ACCOUNT, tagDefinition.getId(), context);
 
         waitALittle();
 
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 e3be801..eabcf09 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
@@ -174,15 +174,13 @@ public class TestIntegrationWithAutoInvoiceOffTag extends TestIntegrationBase {
 
 
     private void add_AUTO_INVOICING_OFF_Tag(final UUID id, final ObjectType type) throws TagDefinitionApiException, TagApiException {
-        final TagDefinition def = tagApi.getTagDefinition(ControlTagType.AUTO_INVOICING_OFF.name());
-        tagApi.addTag(id, type, def, context);
+        tagApi.addTag(id, type, ControlTagType.AUTO_INVOICING_OFF.getId(), context);
         final Map<String, Tag> tags = tagApi.getTags(id, type);
-        assertNotNull(tags.get(ControlTagType.AUTO_INVOICING_OFF.name()));
+        assertEquals(tags.size(), 1);
     }
 
 
     private void remove_AUTO_INVOICING_OFF_Tag(final UUID id, final ObjectType type) throws TagDefinitionApiException, TagApiException {
-        final TagDefinition def = tagApi.getTagDefinition(ControlTagType.AUTO_INVOICING_OFF.name());
-        tagApi.removeTag(id, type, def, context);
+        tagApi.removeTag(id, type, ControlTagType.AUTO_INVOICING_OFF.getId(), context);
     }
 }
diff --git a/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestIntegrationWithAutoPayOff.java b/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestIntegrationWithAutoPayOff.java
index e6ab9d1..8083fdd 100644
--- a/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestIntegrationWithAutoPayOff.java
+++ b/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestIntegrationWithAutoPayOff.java
@@ -281,15 +281,13 @@ public class TestIntegrationWithAutoPayOff extends TestIntegrationBase {
 
 
     private void add_AUTO_PAY_OFF_Tag(final UUID id, final ObjectType type) throws TagDefinitionApiException, TagApiException {
-        final TagDefinition def = tagApi.getTagDefinition(ControlTagType.AUTO_PAY_OFF.name());
-        tagApi.addTag(id, type, def, context);
+        tagApi.addTag(id, type, ControlTagType.AUTO_PAY_OFF.getId(), context);
         final Map<String, Tag> tags = tagApi.getTags(id, type);
-        assertNotNull(tags.get(ControlTagType.AUTO_PAY_OFF.name()));
+        assertEquals(tags.size(), 1);
     }
 
     private void remove_AUTO_PAY_OFF_Tag(final UUID id, final ObjectType type) throws TagDefinitionApiException, TagApiException {
-        final TagDefinition def = tagApi.getTagDefinition(ControlTagType.AUTO_PAY_OFF.name());
-        tagApi.removeTag(id, type, def, context);
+        tagApi.removeTag(id, type, ControlTagType.AUTO_PAY_OFF.getId(), context);
     }
 }
 
diff --git a/beatrix/src/test/resources/resource.properties b/beatrix/src/test/resources/resource.properties
index a2c4ec1..1654b35 100644
--- a/beatrix/src/test/resources/resource.properties
+++ b/beatrix/src/test/resources/resource.properties
@@ -7,5 +7,6 @@ killbill.entitlement.engine.notifications.sleep=100
 killbill.billing.util.persistent.bus.sleep=100
 killbill.billing.util.persistent.bus.nbThreads=1
 user.timezone=UTC
+killbill.payment.retry.days=100,100,100
 
 
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 7b6489d..4c2f636 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
@@ -287,12 +287,12 @@ public class DefaultInvoiceDao implements InvoiceDao {
 
     @Override
     public void setWrittenOff(final UUID invoiceId, final CallContext context) throws TagApiException {
-        tagUserApi.addTag(invoiceId, ObjectType.INVOICE, ControlTagType.WRITTEN_OFF.toTagDefinition(), context);
+        tagUserApi.addTag(invoiceId, ObjectType.INVOICE, ControlTagType.WRITTEN_OFF.getId(), context);
     }
 
     @Override
     public void removeWrittenOff(final UUID invoiceId, final CallContext context) throws TagApiException {
-        tagUserApi.removeTag(invoiceId, ObjectType.INVOICE, ControlTagType.WRITTEN_OFF.toTagDefinition(), context);
+        tagUserApi.removeTag(invoiceId, ObjectType.INVOICE, ControlTagType.WRITTEN_OFF.getId(), context);
     }
 
     @Override
diff --git a/invoice/src/test/java/com/ning/billing/invoice/dao/TestDefaultInvoiceDao.java b/invoice/src/test/java/com/ning/billing/invoice/dao/TestDefaultInvoiceDao.java
index 8c8a947..2bccd7b 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/dao/TestDefaultInvoiceDao.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/dao/TestDefaultInvoiceDao.java
@@ -79,8 +79,8 @@ public class TestDefaultInvoiceDao extends InvoiceTestSuite {
 
         final Map<String, Tag> afterTags = tagUserApi.getTags(invoiceId, ObjectType.INVOICE);
         Assert.assertEquals(afterTags.keySet().size(), 1);
-        final String name = ControlTagType.WRITTEN_OFF.toTagDefinition().getName();
-        Assert.assertEquals(afterTags.get(name).getTagDefinitionName(), name);
+        final UUID tagDefinitionId = ControlTagType.WRITTEN_OFF.getId();
+        Assert.assertEquals(afterTags.values().iterator().next().getTagDefinitionId(), tagDefinitionId);
     }
 
     @Test(groups = "fast")
@@ -91,9 +91,6 @@ public class TestDefaultInvoiceDao extends InvoiceTestSuite {
 
         final Map<String, Tag> beforeTags = tagUserApi.getTags(invoiceId, ObjectType.INVOICE);
         Assert.assertEquals(beforeTags.keySet().size(), 1);
-        final String name = ControlTagType.WRITTEN_OFF.toTagDefinition().getName();
-        Assert.assertEquals(beforeTags.get(name).getTagDefinitionName(), name);
-
         dao.removeWrittenOff(invoiceId, Mockito.mock(CallContext.class));
 
         final Map<String, Tag> afterTags = tagUserApi.getTags(invoiceId, ObjectType.INVOICE);
diff --git a/invoice/src/test/java/com/ning/billing/invoice/dao/TestInvoiceDao.java b/invoice/src/test/java/com/ning/billing/invoice/dao/TestInvoiceDao.java
index 083a3c8..01e628d 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/dao/TestInvoiceDao.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/dao/TestInvoiceDao.java
@@ -1173,7 +1173,7 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
         final TagDao tagDao = new AuditedTagDao(dbi, tagEventBuilder, bus);
         final Map<String, Tag> tags = tagDao.loadEntities(invoice.getId(), ObjectType.INVOICE);
         assertEquals(tags.size(), 1);
-        assertTrue(tags.containsKey(ControlTagType.WRITTEN_OFF.toString()));
+        assertEquals(tags.values().iterator().next().getTagDefinitionId(), ControlTagType.WRITTEN_OFF.getId());
     }
 
     @Test(groups = "slow")
@@ -1204,7 +1204,7 @@ public class TestInvoiceDao extends InvoiceDaoTestBase {
         final TagDao tagDao = new AuditedTagDao(dbi, tagEventBuilder, bus);
         Map<String, Tag> tags = tagDao.loadEntities(invoice.getId(), ObjectType.INVOICE);
         assertEquals(tags.size(), 1);
-        assertTrue(tags.containsKey(ControlTagType.WRITTEN_OFF.toString()));
+        assertEquals(tags.values().iterator().next().getTagDefinitionId(), ControlTagType.WRITTEN_OFF.getId());
 
         invoiceDao.removeWrittenOff(invoice.getId(), context);
         tags = tagDao.loadEntities(invoice.getId(), ObjectType.INVOICE);
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/PaymentJsonWithBundleKeys.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/PaymentJsonWithBundleKeys.java
index 8032fa5..2d71277 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/PaymentJsonWithBundleKeys.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/PaymentJsonWithBundleKeys.java
@@ -24,6 +24,7 @@ import com.fasterxml.jackson.annotation.JsonCreator;
 import com.fasterxml.jackson.annotation.JsonProperty;
 
 public class PaymentJsonWithBundleKeys extends PaymentJsonSimple {
+
     private final String bundleKeys;
 
     public PaymentJsonWithBundleKeys() {
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/TagDefinitionJson.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/TagDefinitionJson.java
index 908f6a0..4ba56e6 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/TagDefinitionJson.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/TagDefinitionJson.java
@@ -1,4 +1,4 @@
-/* 
+/*
  * Copyright 2010-2011 Ning, Inc.
  *
  * Ning licenses this file to you under the Apache License, version 2.0
@@ -21,21 +21,29 @@ import com.fasterxml.jackson.annotation.JsonCreator;
 import com.fasterxml.jackson.annotation.JsonProperty;
 
 public class TagDefinitionJson {
+
+    private final String id;
     private final String name;
     private final String description;
 
     public TagDefinitionJson() {
-        this(null, null);
+        this(null, null, null);
     }
 
     @JsonCreator
-    public TagDefinitionJson(@JsonProperty("name") @Nullable final String name,
-                             @JsonProperty("description") @Nullable final String description) {
+    public TagDefinitionJson(@JsonProperty("id") final String id,
+            @JsonProperty("name") final String name,
+            @JsonProperty("description") @Nullable final String description) {
         super();
+        this.id = id;
         this.name = name;
         this.description = description;
     }
 
+    public String getId() {
+        return id;
+    }
+
     public String getName() {
         return name;
     }
@@ -45,30 +53,50 @@ public class TagDefinitionJson {
     }
 
     @Override
-    public boolean equals(final Object o) {
-        if (this == o) {
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result
+                + ((description == null) ? 0 : description.hashCode());
+        result = prime * result + ((name == null) ? 0 : name.hashCode());
+        result = prime * result
+                + ((id == null) ? 0 : id.hashCode());
+        return result;
+    }
+
+    public boolean equalsNoId(Object obj) {
+        if (this == obj)
             return true;
-        }
-        if (o == null || getClass() != o.getClass()) {
+        if (obj == null)
             return false;
-        }
-
-        final TagDefinitionJson that = (TagDefinitionJson) o;
-
-        if (description != null ? !description.equals(that.description) : that.description != null) {
+        if (getClass() != obj.getClass())
             return false;
-        }
-        if (name != null ? !name.equals(that.name) : that.name != null) {
+        TagDefinitionJson other = (TagDefinitionJson) obj;
+        if (description == null) {
+            if (other.description != null)
+                return false;
+        } else if (!description.equals(other.description))
+            return false;
+        if (name == null) {
+            if (other.name != null)
+                return false;
+        } else if (!name.equals(other.name))
             return false;
-        }
-
         return true;
     }
 
+
     @Override
-    public int hashCode() {
-        int result = name != null ? name.hashCode() : 0;
-        result = 31 * result + (description != null ? description.hashCode() : 0);
-        return result;
+    public boolean equals(Object obj) {
+        if (!equalsNoId(obj)) {
+            return false;
+        }
+        TagDefinitionJson other = (TagDefinitionJson) obj;
+        if (id == null) {
+            if (other.id != null)
+                return false;
+        } else if (!id.equals(other.id))
+            return false;
+        return true;
     }
 }
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/AccountResource.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/AccountResource.java
index 0dec7e0..957e018 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/AccountResource.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/AccountResource.java
@@ -16,6 +16,7 @@
 
 package com.ning.billing.jaxrs.resources;
 
+import static com.ning.billing.jaxrs.resources.JaxrsResource.CUSTOM_FIELDS;
 import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
 
 import java.util.ArrayList;
@@ -71,7 +72,6 @@ import com.ning.billing.jaxrs.json.PaymentMethodJson;
 import com.ning.billing.jaxrs.json.RefundJson;
 import com.ning.billing.jaxrs.util.Context;
 import com.ning.billing.jaxrs.util.JaxrsUriBuilder;
-import com.ning.billing.jaxrs.util.TagHelper;
 import com.ning.billing.payment.api.Payment;
 import com.ning.billing.payment.api.PaymentApi;
 import com.ning.billing.payment.api.PaymentApiException;
@@ -86,8 +86,6 @@ import com.ning.billing.util.dao.ObjectType;
 public class AccountResource extends JaxRsResourceBase {
     private static final Logger log = LoggerFactory.getLogger(AccountResource.class);
     private static final String ID_PARAM_NAME = "accountId";
-    private static final String CUSTOM_FIELD_URI = JaxrsResource.CUSTOM_FIELDS;
-    private static final String TAG_URI = JaxrsResource.TAGS;
 
     private final AccountUserApi accountApi;
     private final EntitlementUserApi entitlementApi;
@@ -106,9 +104,8 @@ public class AccountResource extends JaxRsResourceBase {
                            final EntitlementTimelineApi timelineApi,
                            final CustomFieldUserApi customFieldUserApi,
                            final TagUserApi tagUserApi,
-                           final TagHelper tagHelper,
                            final Context context) {
-        super(uriBuilder, tagUserApi, tagHelper, customFieldUserApi);
+        super(uriBuilder, tagUserApi, customFieldUserApi);
         this.uriBuilder = uriBuilder;
         this.accountApi = accountApi;
         this.entitlementApi = entitlementApi;
@@ -476,14 +473,14 @@ public class AccountResource extends JaxRsResourceBase {
      */
 
     @GET
-    @Path("/{accountId:" + UUID_PATTERN + "}/" + CUSTOM_FIELD_URI)
+    @Path("/{accountId:" + UUID_PATTERN + "}/" + CUSTOM_FIELDS)
     @Produces(APPLICATION_JSON)
     public Response getCustomFields(@PathParam(ID_PARAM_NAME) final String id) {
         return super.getCustomFields(UUID.fromString(id));
     }
 
     @POST
-    @Path("/{accountId:" + UUID_PATTERN + "}/" + CUSTOM_FIELD_URI)
+    @Path("/{accountId:" + UUID_PATTERN + "}/" + CUSTOM_FIELDS)
     @Consumes(APPLICATION_JSON)
     @Produces(APPLICATION_JSON)
     public Response createCustomFields(@PathParam(ID_PARAM_NAME) final String id,
@@ -496,7 +493,7 @@ public class AccountResource extends JaxRsResourceBase {
     }
 
     @DELETE
-    @Path("/{accountId:" + UUID_PATTERN + "}/" + CUSTOM_FIELD_URI)
+    @Path("/{accountId:" + UUID_PATTERN + "}/" + CUSTOM_FIELDS)
     @Consumes(APPLICATION_JSON)
     @Produces(APPLICATION_JSON)
     public Response deleteCustomFields(@PathParam(ID_PARAM_NAME) final String id,
@@ -513,26 +510,27 @@ public class AccountResource extends JaxRsResourceBase {
      */
 
     @GET
-    @Path("/{accountId:" + UUID_PATTERN + "}/" + TAG_URI)
+    @Path("/{accountId:" + UUID_PATTERN + "}/" + TAGS)
     @Produces(APPLICATION_JSON)
     public Response getTags(@PathParam(ID_PARAM_NAME) final String id) {
         return super.getTags(UUID.fromString(id));
     }
 
     @POST
-    @Path("/{accountId:" + UUID_PATTERN + "}/" + TAG_URI)
+    @Path("/{accountId:" + UUID_PATTERN + "}/" + TAGS)
     @Produces(APPLICATION_JSON)
     public Response createTags(@PathParam(ID_PARAM_NAME) final String id,
                                @QueryParam(QUERY_TAGS) final String tagList,
                                @HeaderParam(HDR_CREATED_BY) final String createdBy,
                                @HeaderParam(HDR_REASON) final String reason,
-                               @HeaderParam(HDR_COMMENT) final String comment) {
-        return super.createTags(UUID.fromString(id), tagList,
+                               @HeaderParam(HDR_COMMENT) final String comment,
+                               @javax.ws.rs.core.Context final UriInfo uriInfo) {
+        return super.createTags(UUID.fromString(id), tagList, uriInfo,
                                 context.createContext(createdBy, reason, comment));
     }
 
     @DELETE
-    @Path("/{accountId:" + UUID_PATTERN + "}/" + TAG_URI)
+    @Path("/{accountId:" + UUID_PATTERN + "}/" + TAGS)
     @Consumes(APPLICATION_JSON)
     @Produces(APPLICATION_JSON)
     public Response deleteTags(@PathParam(ID_PARAM_NAME) final String id,
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/BundleResource.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/BundleResource.java
index 5e8877c..3538696 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/BundleResource.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/BundleResource.java
@@ -26,6 +26,7 @@ import javax.ws.rs.PathParam;
 import javax.ws.rs.Produces;
 import javax.ws.rs.QueryParam;
 import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
 import javax.ws.rs.core.Response.Status;
 import java.util.Collection;
 import java.util.List;
@@ -47,7 +48,6 @@ import com.ning.billing.jaxrs.json.CustomFieldJson;
 import com.ning.billing.jaxrs.json.SubscriptionJsonNoEvents;
 import com.ning.billing.jaxrs.util.Context;
 import com.ning.billing.jaxrs.util.JaxrsUriBuilder;
-import com.ning.billing.jaxrs.util.TagHelper;
 import com.ning.billing.util.api.CustomFieldUserApi;
 import com.ning.billing.util.api.TagUserApi;
 import com.ning.billing.util.dao.ObjectType;
@@ -68,9 +68,9 @@ public class BundleResource extends JaxRsResourceBase {
 
     @Inject
     public BundleResource(final JaxrsUriBuilder uriBuilder, final EntitlementUserApi entitlementApi,
-                          final TagUserApi tagUserApi, final TagHelper tagHelper, final CustomFieldUserApi customFieldUserApi,
+                          final TagUserApi tagUserApi, final CustomFieldUserApi customFieldUserApi,
                           final Context context) {
-        super(uriBuilder, tagUserApi, tagHelper, customFieldUserApi);
+        super(uriBuilder, tagUserApi, customFieldUserApi);
         this.uriBuilder = uriBuilder;
         this.entitlementApi = entitlementApi;
         this.context = context;
@@ -207,8 +207,9 @@ public class BundleResource extends JaxRsResourceBase {
                                @QueryParam(QUERY_TAGS) final String tagList,
                                @HeaderParam(HDR_CREATED_BY) final String createdBy,
                                @HeaderParam(HDR_REASON) final String reason,
-                               @HeaderParam(HDR_COMMENT) final String comment) {
-        return super.createTags(UUID.fromString(id), tagList,
+                               @HeaderParam(HDR_COMMENT) final String comment,
+                               @javax.ws.rs.core.Context final UriInfo uriInfo) {
+        return super.createTags(UUID.fromString(id), tagList, uriInfo,
                                 context.createContext(createdBy, reason, comment));
     }
 
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/InvoiceResource.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/InvoiceResource.java
index c4acd5a..22e0e04 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/InvoiceResource.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/InvoiceResource.java
@@ -27,6 +27,7 @@ import javax.ws.rs.PathParam;
 import javax.ws.rs.Produces;
 import javax.ws.rs.QueryParam;
 import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
 import javax.ws.rs.core.Response.Status;
 import java.io.IOException;
 import java.util.ArrayList;
@@ -57,7 +58,6 @@ import com.ning.billing.jaxrs.json.InvoiceJsonWithItems;
 import com.ning.billing.jaxrs.json.PaymentJsonSimple;
 import com.ning.billing.jaxrs.util.Context;
 import com.ning.billing.jaxrs.util.JaxrsUriBuilder;
-import com.ning.billing.jaxrs.util.TagHelper;
 import com.ning.billing.payment.api.Payment;
 import com.ning.billing.payment.api.PaymentApi;
 import com.ning.billing.payment.api.PaymentApiException;
@@ -93,10 +93,9 @@ public class InvoiceResource extends JaxRsResourceBase {
                            final Context context,
                            final JaxrsUriBuilder uriBuilder,
                            final TagUserApi tagUserApi,
-                           final TagHelper tagHelper,
                            final CustomFieldUserApi customFieldUserApi,
                            final InvoiceNotifier invoiceNotifier) {
-        super(uriBuilder, tagUserApi, tagHelper, customFieldUserApi);
+        super(uriBuilder, tagUserApi, customFieldUserApi);
         this.accountApi = accountApi;
         this.invoiceApi = invoiceApi;
         this.paymentApi = paymentApi;
@@ -310,8 +309,9 @@ public class InvoiceResource extends JaxRsResourceBase {
                                @QueryParam(QUERY_TAGS) final String tagList,
                                @HeaderParam(HDR_CREATED_BY) final String createdBy,
                                @HeaderParam(HDR_REASON) final String reason,
-                               @HeaderParam(HDR_COMMENT) final String comment) {
-        return super.createTags(UUID.fromString(id), tagList,
+                               @HeaderParam(HDR_COMMENT) final String comment,
+                               @javax.ws.rs.core.Context final UriInfo uriInfo) {
+        return super.createTags(UUID.fromString(id), tagList, uriInfo,
                                 context.createContext(createdBy, reason, comment));
     }
 
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 8dc98a9..01463ea 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
@@ -17,6 +17,9 @@
 package com.ning.billing.jaxrs.resources;
 
 import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.LinkedList;
@@ -27,9 +30,9 @@ import java.util.UUID;
 import com.google.common.base.Function;
 import com.google.common.base.Preconditions;
 import com.google.common.collect.Collections2;
+import com.google.common.collect.ImmutableList;
 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;
@@ -45,61 +48,75 @@ public abstract class JaxRsResourceBase implements JaxrsResource {
 
     protected final JaxrsUriBuilder uriBuilder;
     protected final TagUserApi tagUserApi;
-    protected final TagHelper tagHelper;
     protected final CustomFieldUserApi customFieldUserApi;
 
     protected abstract ObjectType getObjectType();
 
     public JaxRsResourceBase(final JaxrsUriBuilder uriBuilder,
                              final TagUserApi tagUserApi,
-                             final TagHelper tagHelper,
                              final CustomFieldUserApi customFieldUserApi) {
         this.uriBuilder = uriBuilder;
         this.tagUserApi = tagUserApi;
-        this.tagHelper = tagHelper;
         this.customFieldUserApi = customFieldUserApi;
     }
 
     protected Response getTags(final UUID id) {
-        final Map<String, Tag> tags = tagUserApi.getTags(id, getObjectType());
-        final Collection<String> tagNameList = (tags.size() == 0) ?
-                Collections.<String>emptyList() :
-                Collections2.transform(tags.values(), new Function<Tag, String>() {
-                    @Override
-                    public String apply(final Tag input) {
-                        return input.getTagDefinitionName();
-                    }
-                });
-        return Response.status(Response.Status.OK).entity(tagNameList).build();
+
+        try {
+            final Map<String, Tag> tags = tagUserApi.getTags(id, getObjectType());
+            final Collection<UUID> tagIdList = (tags.size() == 0) ?
+                    Collections.<UUID>emptyList() :
+                        Collections2.transform(tags.values(), new Function<Tag, UUID>() {
+                            @Override
+                            public UUID apply(final Tag input) {
+                                return input.getTagDefinitionId();
+                            }
+                        });
+
+                    final List<TagDefinition> tagDefinitionList = tagUserApi.getTagDefinitions(tagIdList);
+                    return Response.status(Response.Status.OK).entity(tagDefinitionList).build();
+        } catch (TagDefinitionApiException e) {
+            return Response.status(Response.Status.NO_CONTENT).entity(e.getMessage()).build();
+        }
     }
 
     protected Response createTags(final UUID id,
                                   final String tagList,
+                                  final UriInfo uriInfo,
                                   final CallContext context) {
         try {
             Preconditions.checkNotNull(tagList, "Query % list cannot be null", JaxrsResource.QUERY_TAGS);
 
-            final List<TagDefinition> input = tagHelper.getTagDefinitionFromTagList(tagList);
+            final Collection<UUID> input = getTagDefinitionUUIDs(tagList);
             tagUserApi.addTags(id, getObjectType(), input, context);
-
-            return uriBuilder.buildResponse(this.getClass(), "createTags", id);
+            return uriBuilder.buildResponse(this.getClass(), "getTags", id, uriInfo.getBaseUri().toString());
         } catch (IllegalArgumentException e) {
             return Response.status(Response.Status.BAD_REQUEST).entity(e.getMessage()).build();
         } catch (NullPointerException e) {
             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();
         }
     }
 
+
+    private Collection<UUID> getTagDefinitionUUIDs(final String tagList) {
+        final String[] tagParts = tagList.split(",\\s*");
+        final Collection<UUID> result = Collections2.transform(ImmutableList.copyOf(tagParts), new Function<String, UUID>() {
+            @Override
+            public UUID apply(String input) {
+                return UUID.fromString(input);
+            }
+        });
+        return result;
+    }
+
     protected Response deleteTags(final UUID id,
                                   final String tagList,
                                   final CallContext context) {
 
         try {
-            final List<TagDefinition> input = tagHelper.getTagDefinitionFromTagList(tagList);
+            final Collection<UUID> input = getTagDefinitionUUIDs(tagList);
             tagUserApi.removeTags(id, getObjectType(), input, context);
 
             return Response.status(Response.Status.OK).build();
@@ -107,8 +124,6 @@ public abstract class JaxRsResourceBase implements JaxrsResource {
             return Response.status(Response.Status.BAD_REQUEST).entity(e.getMessage()).build();
         } catch (NullPointerException e) {
             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/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/PaymentMethodResource.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/PaymentMethodResource.java
index 339da66..45961b3 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/PaymentMethodResource.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/PaymentMethodResource.java
@@ -1,4 +1,4 @@
-/* 
+/*
  * Copyright 2010-2011 Ning, Inc.
  *
  * Ning licenses this file to you under the Apache License, version 2.0
@@ -40,7 +40,6 @@ import com.ning.billing.account.api.AccountUserApi;
 import com.ning.billing.jaxrs.json.PaymentMethodJson;
 import com.ning.billing.jaxrs.util.Context;
 import com.ning.billing.jaxrs.util.JaxrsUriBuilder;
-import com.ning.billing.jaxrs.util.TagHelper;
 import com.ning.billing.payment.api.PaymentApi;
 import com.ning.billing.payment.api.PaymentApiException;
 import com.ning.billing.payment.api.PaymentMethod;
@@ -62,9 +61,9 @@ public class PaymentMethodResource extends JaxRsResourceBase {
 
     @Inject
     public PaymentMethodResource(final JaxrsUriBuilder uriBuilder, final AccountUserApi accountApi,
-                                 final PaymentApi paymentApi, final TagUserApi tagUserApi, final TagHelper tagHelper,
+                                 final PaymentApi paymentApi, final TagUserApi tagUserApi,
                                  final CustomFieldUserApi customFieldUserApi, final Context context) {
-        super(uriBuilder, tagUserApi, tagHelper, customFieldUserApi);
+        super(uriBuilder, tagUserApi,customFieldUserApi);
         this.paymentApi = paymentApi;
         this.accountApi = accountApi;
         this.context = context;
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/PaymentResource.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/PaymentResource.java
index a4f079d..7b965b0 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/PaymentResource.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/PaymentResource.java
@@ -47,7 +47,6 @@ import com.ning.billing.jaxrs.json.CustomFieldJson;
 import com.ning.billing.jaxrs.json.RefundJson;
 import com.ning.billing.jaxrs.util.Context;
 import com.ning.billing.jaxrs.util.JaxrsUriBuilder;
-import com.ning.billing.jaxrs.util.TagHelper;
 import com.ning.billing.payment.api.Payment;
 import com.ning.billing.payment.api.PaymentApi;
 import com.ning.billing.payment.api.PaymentApiException;
@@ -74,10 +73,9 @@ public class PaymentResource extends JaxRsResourceBase {
             final AccountUserApi accountApi,
             final PaymentApi paymentApi,
             final TagUserApi tagUserApi,
-            final TagHelper tagHelper,
             final CustomFieldUserApi customFieldUserApi,
             final Context context) {
-        super(uriBuilder, tagUserApi, tagHelper, customFieldUserApi);
+        super(uriBuilder, tagUserApi, customFieldUserApi);
         this.context = context;
         this.paymentApi = paymentApi;
         this.accountApi = accountApi;
@@ -182,8 +180,9 @@ public class PaymentResource extends JaxRsResourceBase {
                                @QueryParam(QUERY_TAGS) final String tagList,
                                @HeaderParam(HDR_CREATED_BY) final String createdBy,
                                @HeaderParam(HDR_REASON) final String reason,
-                               @HeaderParam(HDR_COMMENT) final String comment) {
-        return super.createTags(UUID.fromString(id), tagList,
+                               @HeaderParam(HDR_COMMENT) final String comment,
+                               @javax.ws.rs.core.Context final UriInfo uriInfo) {
+        return super.createTags(UUID.fromString(id), tagList, uriInfo,
                                 context.createContext(createdBy, reason, comment));
     }
 
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/RefundResource.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/RefundResource.java
index 6a5a729..b67fb68 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/RefundResource.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/RefundResource.java
@@ -37,7 +37,6 @@ import com.ning.billing.ErrorCode;
 import com.ning.billing.jaxrs.json.RefundJson;
 import com.ning.billing.jaxrs.util.Context;
 import com.ning.billing.jaxrs.util.JaxrsUriBuilder;
-import com.ning.billing.jaxrs.util.TagHelper;
 import com.ning.billing.payment.api.PaymentApi;
 import com.ning.billing.payment.api.PaymentApiException;
 import com.ning.billing.payment.api.Refund;
@@ -57,10 +56,9 @@ public class RefundResource extends JaxRsResourceBase {
     public RefundResource(final JaxrsUriBuilder uriBuilder,
             final PaymentApi paymentApi,
             final TagUserApi tagUserApi,
-            final TagHelper tagHelper,
             final CustomFieldUserApi customFieldUserApi,
             final Context context) {
-        super(uriBuilder, tagUserApi, tagHelper, customFieldUserApi);
+        super(uriBuilder, tagUserApi, customFieldUserApi);
         this.paymentApi = paymentApi;
     }
 
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/SubscriptionResource.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/SubscriptionResource.java
index 6cb4de1..d870189 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/SubscriptionResource.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/SubscriptionResource.java
@@ -28,6 +28,7 @@ import javax.ws.rs.PathParam;
 import javax.ws.rs.Produces;
 import javax.ws.rs.QueryParam;
 import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
 import javax.ws.rs.core.Response.Status;
 import java.math.BigDecimal;
 import java.util.List;
@@ -56,7 +57,6 @@ import com.ning.billing.jaxrs.json.SubscriptionJsonNoEvents;
 import com.ning.billing.jaxrs.util.Context;
 import com.ning.billing.jaxrs.util.JaxrsUriBuilder;
 import com.ning.billing.jaxrs.util.KillbillEventHandler;
-import com.ning.billing.jaxrs.util.TagHelper;
 import com.ning.billing.payment.api.PaymentErrorEvent;
 import com.ning.billing.payment.api.PaymentInfoEvent;
 import com.ning.billing.util.api.CustomFieldUserApi;
@@ -84,8 +84,8 @@ public class SubscriptionResource extends JaxRsResourceBase {
     @Inject
     public SubscriptionResource(final JaxrsUriBuilder uriBuilder, final EntitlementUserApi entitlementApi,
             final Context context, final KillbillEventHandler killbillHandler,
-            final TagUserApi tagUserApi, final TagHelper tagHelper, final CustomFieldUserApi customFieldUserApi) {
-        super(uriBuilder, tagUserApi, tagHelper, customFieldUserApi);
+            final TagUserApi tagUserApi, final CustomFieldUserApi customFieldUserApi) {
+        super(uriBuilder, tagUserApi, customFieldUserApi);
         this.uriBuilder = uriBuilder;
         this.entitlementApi = entitlementApi;
         this.context = context;
@@ -290,19 +290,19 @@ public class SubscriptionResource extends JaxRsResourceBase {
 
         @Override
         public void onSubscriptionTransition(EffectiveSubscriptionEvent curEventEffective) {
-            log.info(String.format("Got event SubscriptionTransition token = %s, type = %s, remaining = %d ", 
+            log.info(String.format("Got event SubscriptionTransition token = %s, type = %s, remaining = %d ",
                     curEventEffective.getUserToken(), curEventEffective.getTransitionType(),  curEventEffective.getRemainingEventsForUserOperation()));
         }
 
         @Override
         public void onEmptyInvoice(final NullInvoiceEvent curEvent) {
-            log.info(String.format("Got event EmptyInvoiceNotification token = %s ", curEvent.getUserToken())); 
+            log.info(String.format("Got event EmptyInvoiceNotification token = %s ", curEvent.getUserToken()));
             notifyForCompletion();
         }
 
         @Override
         public void onInvoiceCreation(InvoiceCreationEvent curEvent) {
-            log.info(String.format("Got event InvoiceCreationNotification token = %s ", curEvent.getUserToken())); 
+            log.info(String.format("Got event InvoiceCreationNotification token = %s ", curEvent.getUserToken()));
             if (curEvent.getAmountOwed().compareTo(BigDecimal.ZERO) <= 0) {
                 notifyForCompletion();
             }
@@ -310,13 +310,13 @@ public class SubscriptionResource extends JaxRsResourceBase {
 
         @Override
         public void onPaymentInfo(PaymentInfoEvent curEvent) {
-            log.info(String.format("Got event PaymentInfo token = %s ", curEvent.getUserToken()));  
+            log.info(String.format("Got event PaymentInfo token = %s ", curEvent.getUserToken()));
             notifyForCompletion();
         }
 
         @Override
         public void onPaymentError(PaymentErrorEvent curEvent) {
-            log.info(String.format("Got event PaymentError token = %s ", curEvent.getUserToken())); 
+            log.info(String.format("Got event PaymentError token = %s ", curEvent.getUserToken()));
             notifyForCompletion();
         }
     }
@@ -412,8 +412,9 @@ public class SubscriptionResource extends JaxRsResourceBase {
             @QueryParam(QUERY_TAGS) final String tagList,
             @HeaderParam(HDR_CREATED_BY) final String createdBy,
             @HeaderParam(HDR_REASON) final String reason,
-            @HeaderParam(HDR_COMMENT) final String comment) {
-        return super.createTags(UUID.fromString(id), tagList,
+            @HeaderParam(HDR_COMMENT) final String comment,
+            @javax.ws.rs.core.Context final UriInfo uriInfo) {
+        return super.createTags(UUID.fromString(id), tagList, uriInfo,
                 context.createContext(createdBy, reason, comment));
     }
 
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/TagResource.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/TagResource.java
index ecb7242..89408ea 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/TagResource.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/TagResource.java
@@ -28,6 +28,7 @@ import javax.ws.rs.core.Response;
 import javax.ws.rs.core.Response.Status;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.UUID;
 
 import com.google.inject.Inject;
 import com.google.inject.Singleton;
@@ -62,18 +63,18 @@ public class TagResource implements JaxrsResource {
         final List<TagDefinitionJson> result = new LinkedList<TagDefinitionJson>();
         final List<TagDefinition> tagDefinitions = tagUserApi.getTagDefinitions();
         for (final TagDefinition cur : tagDefinitions) {
-            result.add(new TagDefinitionJson(cur.getName(), cur.getDescription()));
+            result.add(new TagDefinitionJson(cur.getId().toString(), cur.getName(), cur.getDescription()));
         }
         return Response.status(Status.OK).entity(result).build();
     }
 
     @GET
-    @Path("/{tagDefinitionName:" + STRING_PATTERN + "}")
+    @Path("/{tagDefinitionId:" + UUID_PATTERN + "}")
     @Produces(APPLICATION_JSON)
-    public Response getTagDefinition(@PathParam("tagDefinitionName") final String tagDefName) {
+    public Response getTagDefinition(@PathParam("tagDefinitionId") final String tagDefId) {
         try {
-            final TagDefinition tagDef = tagUserApi.getTagDefinition(tagDefName);
-            final TagDefinitionJson json = new TagDefinitionJson(tagDef.getName(), tagDef.getDescription());
+            final TagDefinition tagDef = tagUserApi.getTagDefinition(UUID.fromString(tagDefId));
+            final TagDefinitionJson json = new TagDefinitionJson(tagDef.getId().toString(), tagDef.getName(), tagDef.getDescription());
             return Response.status(Status.OK).entity(json).build();
         } catch (TagDefinitionApiException e) {
             return Response.status(Status.NO_CONTENT).build();
@@ -85,12 +86,12 @@ public class TagResource implements JaxrsResource {
     @Consumes(APPLICATION_JSON)
     @Produces(APPLICATION_JSON)
     public Response createTagDefinition(final TagDefinitionJson json,
-                                        @HeaderParam(HDR_CREATED_BY) final String createdBy,
-                                        @HeaderParam(HDR_REASON) final String reason,
-                                        @HeaderParam(HDR_COMMENT) final String comment) {
+            @HeaderParam(HDR_CREATED_BY) final String createdBy,
+            @HeaderParam(HDR_REASON) final String reason,
+            @HeaderParam(HDR_COMMENT) final String comment) {
         try {
             final TagDefinition createdTagDef = tagUserApi.create(json.getName(), json.getDescription(), context.createContext(createdBy, reason, comment));
-            return uriBuilder.buildResponse(TagResource.class, "getTagDefinition", createdTagDef.getName());
+            return uriBuilder.buildResponse(TagResource.class, "getTagDefinition", createdTagDef.getId());
         } catch (TagDefinitionApiException e) {
             return Response.status(Status.NO_CONTENT).build();
         } catch (IllegalArgumentException e) {
@@ -99,15 +100,15 @@ public class TagResource implements JaxrsResource {
     }
 
     @DELETE
-    @Path("/{tagDefinitionName:" + STRING_PATTERN + "}")
+    @Path("/{tagDefinitionId:" + UUID_PATTERN + "}")
     @Produces(APPLICATION_JSON)
-    public Response deleteTagDefinition(@PathParam("tagDefinitionName") final String tagDefName,
-                                        @HeaderParam(HDR_CREATED_BY) final String createdBy,
-                                        @HeaderParam(HDR_REASON) final String reason,
-                                        @HeaderParam(HDR_COMMENT) final String comment) {
+    public Response deleteTagDefinition(@PathParam("tagDefinitionId") final String tagDefId,
+            @HeaderParam(HDR_CREATED_BY) final String createdBy,
+            @HeaderParam(HDR_REASON) final String reason,
+            @HeaderParam(HDR_COMMENT) final String comment) {
         try {
-            tagUserApi.deleteTagDefinition(tagDefName, context.createContext(createdBy, reason, comment));
-            return Response.status(Status.NO_CONTENT).build();
+            tagUserApi.deleteTagDefinition(UUID.fromString(tagDefId), context.createContext(createdBy, reason, comment));
+            return Response.status(Status.OK).build();
         } catch (TagDefinitionApiException e) {
             return Response.status(Status.NO_CONTENT).build();
         } catch (IllegalArgumentException e) {
diff --git a/jaxrs/src/test/java/com/ning/billing/jaxrs/json/TestTagDefinitionJson.java b/jaxrs/src/test/java/com/ning/billing/jaxrs/json/TestTagDefinitionJson.java
index d771085..01850a0 100644
--- a/jaxrs/src/test/java/com/ning/billing/jaxrs/json/TestTagDefinitionJson.java
+++ b/jaxrs/src/test/java/com/ning/billing/jaxrs/json/TestTagDefinitionJson.java
@@ -29,14 +29,16 @@ public class TestTagDefinitionJson extends JaxrsTestSuite {
 
     @Test(groups = "fast")
     public void testJson() throws Exception {
+        final String id = UUID.randomUUID().toString();
         final String name = UUID.randomUUID().toString();
         final String description = UUID.randomUUID().toString();
-        final TagDefinitionJson tagDefinitionJson = new TagDefinitionJson(name, description);
+        final TagDefinitionJson tagDefinitionJson = new TagDefinitionJson(id, name, description);
         Assert.assertEquals(tagDefinitionJson.getName(), name);
         Assert.assertEquals(tagDefinitionJson.getDescription(), description);
 
         final String asJson = mapper.writeValueAsString(tagDefinitionJson);
-        Assert.assertEquals(asJson, "{\"name\":\"" + tagDefinitionJson.getName() + "\"," +
+        Assert.assertEquals(asJson, "{\"id\":\"" + tagDefinitionJson.getId() + "\"," +
+                "\"name\":\"" + tagDefinitionJson.getName() + "\"," +
                 "\"description\":\"" + tagDefinitionJson.getDescription() + "\"}");
 
         final TagDefinitionJson fromJson = mapper.readValue(asJson, TagDefinitionJson.class);
diff --git a/junction/src/main/java/com/ning/billing/junction/plumbing/billing/DefaultBillingApi.java b/junction/src/main/java/com/ning/billing/junction/plumbing/billing/DefaultBillingApi.java
index 3c1cf31..d8b1bc3 100644
--- a/junction/src/main/java/com/ning/billing/junction/plumbing/billing/DefaultBillingApi.java
+++ b/junction/src/main/java/com/ning/billing/junction/plumbing/billing/DefaultBillingApi.java
@@ -92,9 +92,11 @@ public class DefaultBillingApi implements BillingApi {
 
             // Check to see if billing is off for the account
             final Map<String, Tag> accountTags = tagApi.getTags(accountId, ObjectType.ACCOUNT);
-            if (accountTags.get(ControlTagType.AUTO_INVOICING_OFF.name()) != null) {
-                result.setAccountAutoInvoiceIsOff(true);
-                return result; // billing is off, we are done
+            for (Tag cur : accountTags.values()) {
+                if (ControlTagType.AUTO_INVOICING_OFF.getId().equals(cur.getTagDefinitionId())) {
+                    result.setAccountAutoInvoiceIsOff(true);
+                    return result; // billing is off, we are done
+                }
             }
 
             addBillingEventsForBundles(bundles, account, context, result);
@@ -124,7 +126,15 @@ public class DefaultBillingApi implements BillingApi {
 
             //Check if billing is off for the bundle
             final Map<String, Tag> bundleTags = tagApi.getTags(bundle.getId(), ObjectType.BUNDLE);
-            if (bundleTags.get(ControlTagType.AUTO_INVOICING_OFF.name()) != null) {
+
+            boolean found_AUTO_INVOICING_OFF = false;
+            for (Tag cur : bundleTags.values()) {
+                if (ControlTagType.AUTO_INVOICING_OFF.getId().equals(cur.getTagDefinitionId())) {
+                    found_AUTO_INVOICING_OFF = true;
+                    break;
+                }
+            }
+            if (found_AUTO_INVOICING_OFF) {
                 for (final Subscription subscription : subscriptions) { // billing is off so list sub ids in set to be excluded
                     result.getSubscriptionIdsWithAutoInvoiceOff().add(subscription.getId());
                 }
diff --git a/junction/src/test/java/com/ning/billing/junction/plumbing/billing/TestBillingApi.java b/junction/src/test/java/com/ning/billing/junction/plumbing/billing/TestBillingApi.java
index 8a290d9..caccc9c 100644
--- a/junction/src/test/java/com/ning/billing/junction/plumbing/billing/TestBillingApi.java
+++ b/junction/src/test/java/com/ning/billing/junction/plumbing/billing/TestBillingApi.java
@@ -437,7 +437,7 @@ public class TestBillingApi extends JunctionTestSuite {
 
         final Map<String, Tag> tags = new HashMap<String, Tag>();
         final Tag aioTag = mock(Tag.class);
-        when(aioTag.getTagDefinitionName()).thenReturn(ControlTagType.AUTO_INVOICING_OFF.name());
+        when(aioTag.getTagDefinitionId()).thenReturn(ControlTagType.AUTO_INVOICING_OFF.getId());
         tags.put(ControlTagType.AUTO_INVOICING_OFF.name(), aioTag);
         when(tagApi.getTags(account.getId(), ObjectType.ACCOUNT)).thenReturn(tags);
         assertEquals(tagApi.getTags(account.getId(), ObjectType.ACCOUNT), tags);
@@ -479,7 +479,7 @@ public class TestBillingApi extends JunctionTestSuite {
 
         final Map<String, Tag> tags = new HashMap<String, Tag>();
         final Tag aioTag = mock(Tag.class);
-        when(aioTag.getTagDefinitionName()).thenReturn(ControlTagType.AUTO_INVOICING_OFF.name());
+        when(aioTag.getTagDefinitionId()).thenReturn(ControlTagType.AUTO_INVOICING_OFF.getId());
         tags.put(ControlTagType.AUTO_INVOICING_OFF.name(), aioTag);
         when(tagApi.getTags(bunId, ObjectType.BUNDLE)).thenReturn(tags);
 
diff --git a/overdue/src/main/java/com/ning/billing/overdue/config/DefaultCondition.java b/overdue/src/main/java/com/ning/billing/overdue/config/DefaultCondition.java
index 58b2e81..cd50142 100644
--- a/overdue/src/main/java/com/ning/billing/overdue/config/DefaultCondition.java
+++ b/overdue/src/main/java/com/ning/billing/overdue/config/DefaultCondition.java
@@ -83,9 +83,9 @@ public class DefaultCondition<T extends Blockable> extends ValidatingConfig<Over
         return false;
     }
 
-    private boolean isTagIn(final ControlTagType tag, final Tag[] tags) {
+    private boolean isTagIn(final ControlTagType tagType, final Tag[] tags) {
         for (final Tag t : tags) {
-            if (t.getTagDefinitionName().equals(tag.toString())) {
+            if (t.getTagDefinitionId().equals(tagType.getId())) {
                 return true;
             }
         }
diff --git a/overdue/src/test/java/com/ning/billing/overdue/config/TestCondition.java b/overdue/src/test/java/com/ning/billing/overdue/config/TestCondition.java
index 4fc1ded..1531a8a 100644
--- a/overdue/src/test/java/com/ning/billing/overdue/config/TestCondition.java
+++ b/overdue/src/test/java/com/ning/billing/overdue/config/TestCondition.java
@@ -148,7 +148,7 @@ public class TestCondition extends OverdueTestSuite {
         final LocalDate now = new LocalDate();
 
         final BillingState<Blockable> state0 = new BillingState<Blockable>(new UUID(0L, 1L), 0, BigDecimal.ZERO, null,
-                                                                           DateTimeZone.UTC, unpaidInvoiceId, PaymentResponse.LOST_OR_STOLEN_CARD, new Tag[]{new DefaultControlTag(ControlTagType.AUTO_INVOICING_OFF), new DescriptiveTag("Tag")});
+                                                                           DateTimeZone.UTC, unpaidInvoiceId, PaymentResponse.LOST_OR_STOLEN_CARD, new Tag[]{new DefaultControlTag(ControlTagType.AUTO_INVOICING_OFF), new DescriptiveTag(UUID.randomUUID())});
         final BillingState<Blockable> state1 = new BillingState<Blockable>(new UUID(0L, 1L), 1, new BigDecimal("100.00"), now.minusDays(10),
                                                                            DateTimeZone.UTC, unpaidInvoiceId, PaymentResponse.INSUFFICIENT_FUNDS, new Tag[]{new DefaultControlTag(ControlTagType.OVERDUE_ENFORCEMENT_OFF)});
         final BillingState<Blockable> state2 = new BillingState<Blockable>(new UUID(0L, 1L), 1, new BigDecimal("200.00"), now.minusDays(20),
@@ -156,7 +156,7 @@ public class TestCondition extends OverdueTestSuite {
                                                                            PaymentResponse.DO_NOT_HONOR,
                                                                            new Tag[]{new DefaultControlTag(ControlTagType.OVERDUE_ENFORCEMENT_OFF),
                                                                                      new DefaultControlTag(ControlTagType.AUTO_INVOICING_OFF),
-                                                                                     new DescriptiveTag("Tag")});
+                                                                                     new DescriptiveTag(UUID.randomUUID())});
 
         Assert.assertTrue(!c.evaluate(state0, now));
         Assert.assertTrue(c.evaluate(state1, now));
diff --git a/payment/src/main/java/com/ning/billing/payment/core/PaymentProcessor.java b/payment/src/main/java/com/ning/billing/payment/core/PaymentProcessor.java
index 46f2cfd..c09bad9 100644
--- a/payment/src/main/java/com/ning/billing/payment/core/PaymentProcessor.java
+++ b/payment/src/main/java/com/ning/billing/payment/core/PaymentProcessor.java
@@ -284,7 +284,7 @@ public class PaymentProcessor extends ProcessorBase {
                 }));
                 log.warn(String.format("Setting account %s into AUTO_PAY_OFF because of bad payments : %s", accountId, JOINER.toString()));
                 try {
-                    tagUserApi.addTag(accountId, ObjectType.ACCOUNT, ControlTagType.AUTO_PAY_OFF.toTagDefinition(), context);
+                    tagUserApi.addTag(accountId, ObjectType.ACCOUNT, ControlTagType.AUTO_PAY_OFF.getId(), context);
                 } catch (TagApiException e) {
                     log.error("Failed to add AUTO_PAY_OFF on account " + accountId, e);
                     throw new PaymentApiException(ErrorCode.PAYMENT_INTERNAL_ERROR, "Failed to add AUTO_PAY_OFF on account " + accountId);
@@ -330,7 +330,7 @@ public class PaymentProcessor extends ProcessorBase {
     private boolean isAccountAutoPayOff(final UUID accountId) {
         final Map<String, Tag> accountTags = tagUserApi.getTags(accountId, ObjectType.ACCOUNT);
         for (final Tag cur : accountTags.values()) {
-            if (cur.getTagDefinitionName().equals(ControlTagType.AUTO_PAY_OFF.toString())) {
+            if (ControlTagType.AUTO_PAY_OFF.getId().equals(cur.getTagDefinitionId())) {
                 return true;
             }
         }
diff --git a/server/src/main/java/com/ning/billing/server/modules/KillbillServerModule.java b/server/src/main/java/com/ning/billing/server/modules/KillbillServerModule.java
index 96c8668..fda58c0 100644
--- a/server/src/main/java/com/ning/billing/server/modules/KillbillServerModule.java
+++ b/server/src/main/java/com/ning/billing/server/modules/KillbillServerModule.java
@@ -37,7 +37,6 @@ import com.ning.billing.jaxrs.resources.RefundResource;
 import com.ning.billing.jaxrs.resources.SubscriptionResource;
 import com.ning.billing.jaxrs.resources.TagResource;
 import com.ning.billing.jaxrs.util.KillbillEventHandler;
-import com.ning.billing.jaxrs.util.TagHelper;
 import com.ning.billing.junction.glue.DefaultJunctionModule;
 import com.ning.billing.payment.glue.PaymentModule;
 import com.ning.billing.util.email.EmailModule;
@@ -71,7 +70,6 @@ public class KillbillServerModule extends AbstractModule {
     }
 
     protected void configureResources() {
-        bind(TagHelper.class).asEagerSingleton();
         bind(AccountResource.class).asEagerSingleton();
         bind(BundleResource.class).asEagerSingleton();
         bind(SubscriptionResource.class).asEagerSingleton();
diff --git a/server/src/test/java/com/ning/billing/jaxrs/TestAccount.java b/server/src/test/java/com/ning/billing/jaxrs/TestAccount.java
index 791da29..ae1f20e 100644
--- a/server/src/test/java/com/ning/billing/jaxrs/TestAccount.java
+++ b/server/src/test/java/com/ning/billing/jaxrs/TestAccount.java
@@ -273,24 +273,16 @@ public class TestAccount extends TestJaxrsBase {
 
     @Test(groups = "slow", enabled = true)
     public void testTags() throws Exception {
-        //Create Tag definition
-        final TagDefinitionJson input = new TagDefinitionJson("yoyo", "nothing more to say");
-        final String baseJson = mapper.writeValueAsString(input);
-        Response response = doPost(JaxrsResource.TAG_DEFINITIONS_PATH, baseJson, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
-        assertEquals(response.getStatusCode(), Status.CREATED.getStatusCode());
+
+        // Use tag definition for AUTO_PAY_OFF
+        final TagDefinitionJson input = new TagDefinitionJson(new UUID(0, 1).toString(), "AUTO_PAY_OFF", "nothing more to say");
 
         final Map<String, String> queryParams = new HashMap<String, String>();
-        queryParams.put(JaxrsResource.QUERY_TAGS, input.getName());
+        queryParams.put(JaxrsResource.QUERY_TAGS, input.getId());
         final String uri = JaxrsResource.ACCOUNTS_PATH + "/" + UUID.randomUUID().toString() + "/" + JaxrsResource.TAGS;
-        response = doPost(uri, null, queryParams, DEFAULT_HTTP_TIMEOUT_SEC);
-
+        Response response = doPost(uri, null, queryParams, DEFAULT_HTTP_TIMEOUT_SEC);
         assertEquals(response.getStatusCode(), Status.CREATED.getStatusCode());
 
-        /*
-         * STEPH Some how Location returns the ID twice (confused) :
-         * Location: http://127.0.0.1:8080/1.0/kb/accounts/tags/ebb5f830-6f0a-4521-9553-521d173169be/ebb5f830-6f0a-4521-9553-521d173169be
-         */
-
         // Retrieves by Id based on Location returned
         final String url = getUrlFromUri(uri);
         response = doGetWithUrl(url, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
diff --git a/server/src/test/java/com/ning/billing/jaxrs/TestTag.java b/server/src/test/java/com/ning/billing/jaxrs/TestTag.java
index a4f0002..174fab1 100644
--- a/server/src/test/java/com/ning/billing/jaxrs/TestTag.java
+++ b/server/src/test/java/com/ning/billing/jaxrs/TestTag.java
@@ -1,4 +1,4 @@
-/* 
+/*
  * Copyright 2010-2011 Ning, Inc.
  *
  * Ning licenses this file to you under the Apache License, version 2.0
@@ -18,6 +18,7 @@ package com.ning.billing.jaxrs;
 import javax.ws.rs.core.Response.Status;
 import java.util.List;
 
+import org.testng.Assert;
 import org.testng.annotations.Test;
 
 import com.fasterxml.jackson.core.type.TypeReference;
@@ -27,12 +28,13 @@ import com.ning.http.client.Response;
 
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
 
 public class TestTag extends TestJaxrsBase {
     @Test(groups = "slow", enabled = true)
     public void testTagDefinitionOk() throws Exception {
 
-        final TagDefinitionJson input = new TagDefinitionJson("blue", "relaxing color");
+        final TagDefinitionJson input = new TagDefinitionJson(null, "blue", "relaxing color");
         String baseJson = mapper.writeValueAsString(input);
         Response response = doPost(JaxrsResource.TAG_DEFINITIONS_PATH, baseJson, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
         assertEquals(response.getStatusCode(), Status.CREATED.getStatusCode());
@@ -47,7 +49,7 @@ public class TestTag extends TestJaxrsBase {
         baseJson = response.getResponseBody();
         final TagDefinitionJson objFromJson = mapper.readValue(baseJson, TagDefinitionJson.class);
         assertNotNull(objFromJson);
-        assertEquals(objFromJson, input);
+        assertTrue(objFromJson.equalsNoId(input));
     }
 
     @Test(groups = "slow", enabled = true)
@@ -60,23 +62,23 @@ public class TestTag extends TestJaxrsBase {
         List<TagDefinitionJson> objFromJson = mapper.readValue(baseJson, new TypeReference<List<TagDefinitionJson>>() {});
         final int sizeSystemTag = (objFromJson == null || objFromJson.size() == 0) ? 0 : objFromJson.size();
 
-        TagDefinitionJson input = new TagDefinitionJson("blue", "relaxing color");
-        baseJson = mapper.writeValueAsString(input);
+        TagDefinitionJson inputBlue = new TagDefinitionJson(null, "blue", "relaxing color");
+        baseJson = mapper.writeValueAsString(inputBlue);
         response = doPost(JaxrsResource.TAG_DEFINITIONS_PATH, baseJson, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
         assertEquals(response.getStatusCode(), Status.CREATED.getStatusCode());
 
-        input = new TagDefinitionJson("red", "hot color");
-        baseJson = mapper.writeValueAsString(input);
+        TagDefinitionJson inputRed = new TagDefinitionJson(null, "red", "hot color");
+        baseJson = mapper.writeValueAsString(inputRed);
         response = doPost(JaxrsResource.TAG_DEFINITIONS_PATH, baseJson, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
         assertEquals(response.getStatusCode(), Status.CREATED.getStatusCode());
 
-        input = new TagDefinitionJson("yellow", "vibrant color");
-        baseJson = mapper.writeValueAsString(input);
+        TagDefinitionJson inputYellow = new TagDefinitionJson(null, "yellow", "vibrant color");
+        baseJson = mapper.writeValueAsString(inputYellow);
         response = doPost(JaxrsResource.TAG_DEFINITIONS_PATH, baseJson, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
         assertEquals(response.getStatusCode(), Status.CREATED.getStatusCode());
 
-        input = new TagDefinitionJson("green", "super relaxing color");
-        baseJson = mapper.writeValueAsString(input);
+        TagDefinitionJson inputGreen = new TagDefinitionJson(null, "green", "super relaxing color");
+        baseJson = mapper.writeValueAsString(inputGreen);
         response = doPost(JaxrsResource.TAG_DEFINITIONS_PATH, baseJson, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
         assertEquals(response.getStatusCode(), Status.CREATED.getStatusCode());
 
@@ -88,21 +90,20 @@ public class TestTag extends TestJaxrsBase {
         assertNotNull(objFromJson);
         assertEquals(objFromJson.size(), 4 + sizeSystemTag);
 
-        // STEPH currently broken Tag API does not work as expected...
 
-        /*
-        String uri = JaxrsResource.TAG_DEFINITIONS_PATH + "/green";
+
+        String uri = JaxrsResource.TAG_DEFINITIONS_PATH + "/" + objFromJson.get(0).getId();
         response = doDelete(uri, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
-        assertEquals(response.getStatusCode(), Status.NO_CONTENT.getStatusCode());
-    
+        assertEquals(response.getStatusCode(), Status.OK.getStatusCode());
+
         response = doGet(JaxrsResource.TAG_DEFINITIONS_PATH, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
         assertEquals(response.getStatusCode(), Status.OK.getStatusCode());
         baseJson = response.getResponseBody();
-        
+
         objFromJson = mapper.readValue(baseJson, new TypeReference<List<TagDefinitionJson>>() {});
         assertNotNull(objFromJson);
         assertEquals(objFromJson.size(), 3 + sizeSystemTag);
-        */
+
     }
 
 }
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 075e10e..ce09032 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
@@ -16,6 +16,7 @@
 
 package com.ning.billing.util.tag.api;
 
+import java.util.Collection;
 import java.util.List;
 import java.util.Map;
 import java.util.UUID;
@@ -52,39 +53,46 @@ public class DefaultTagUserApi implements TagUserApi {
     }
 
     @Override
-    public void deleteTagDefinition(final String definitionName, final CallContext context) throws TagDefinitionApiException {
-        tagDefinitionDao.deleteTagDefinition(definitionName, context);
+    public void deleteTagDefinition(final UUID definitionId, final CallContext context) throws TagDefinitionApiException {
+        tagDefinitionDao.deleteById(definitionId, context);
     }
 
     @Override
-    public TagDefinition getTagDefinition(final String name)
+    public TagDefinition getTagDefinition(final UUID tagDefinitionId)
             throws TagDefinitionApiException {
-        return tagDefinitionDao.getByName(name);
+        return tagDefinitionDao.getById(tagDefinitionId);
+    }
+
+
+    @Override
+    public List<TagDefinition> getTagDefinitions(Collection<UUID> tagDefinitionIds)
+            throws TagDefinitionApiException {
+        return tagDefinitionDao.getByIds(tagDefinitionIds);
     }
 
     @Override
-    public void addTags(final UUID objectId, final ObjectType objectType, final List<TagDefinition> tagDefinitions, final CallContext context) throws TagApiException {
+    public void addTags(final UUID objectId, final ObjectType objectType, final Collection<UUID> tagDefinitionIds, final CallContext context) throws TagApiException {
         // TODO: consider making this batch
-        for (final TagDefinition tagDefinition : tagDefinitions) {
-            tagDao.insertTag(objectId, objectType, tagDefinition, context);
+        for (final UUID tagDefinitionId : tagDefinitionIds) {
+            tagDao.insertTag(objectId, objectType, tagDefinitionId, context);
         }
     }
 
     @Override
-    public void addTag(final UUID objectId, final ObjectType objectType, final TagDefinition tagDefinition, final CallContext context) throws TagApiException {
-        tagDao.insertTag(objectId, objectType, tagDefinition, context);
+    public void addTag(final UUID objectId, final ObjectType objectType, final UUID tagDefinitionId, final CallContext context) throws TagApiException {
+        tagDao.insertTag(objectId, objectType, tagDefinitionId, context);
     }
 
     @Override
-    public void removeTag(final UUID objectId, final ObjectType objectType, final TagDefinition tagDefinition, final CallContext context) throws TagApiException {
-        tagDao.deleteTag(objectId, objectType, tagDefinition, context);
+    public void removeTag(final UUID objectId, final ObjectType objectType, final UUID tagDefinitionId, final CallContext context) throws TagApiException {
+        tagDao.deleteTag(objectId, objectType, tagDefinitionId, context);
     }
 
     @Override
-    public void removeTags(final UUID objectId, final ObjectType objectType, final List<TagDefinition> tagDefinitions, final CallContext context) throws TagApiException {
+    public void removeTags(final UUID objectId, final ObjectType objectType, final Collection<UUID> tagDefinitionIds, final CallContext context) throws TagApiException {
         // TODO: consider making this batch
-        for (final TagDefinition tagDefinition : tagDefinitions) {
-            tagDao.deleteTag(objectId, objectType, tagDefinition, context);
+        for (final UUID tagDefinitionId : tagDefinitionIds) {
+            tagDao.deleteTag(objectId, objectType, tagDefinitionId, context);
         }
     }
 
@@ -92,4 +100,10 @@ public class DefaultTagUserApi implements TagUserApi {
     public Map<String, Tag> getTags(final UUID objectId, final ObjectType objectType) {
         return tagDao.loadEntities(objectId, objectType);
     }
+
+    @Override
+    public TagDefinition getTagDefinitionForName(String tagDefinitionName)
+            throws TagDefinitionApiException {
+        return tagDefinitionDao.getByName(tagDefinitionName);
+    }
 }
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 d990f7e..7cf580e 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
@@ -43,6 +43,8 @@ import com.ning.billing.util.dao.Mapper;
 import com.ning.billing.util.dao.ObjectType;
 import com.ning.billing.util.dao.TableName;
 import com.ning.billing.util.entity.collection.dao.UpdatableEntityCollectionSqlDao;
+import com.ning.billing.util.tag.ControlTagType;
+import com.ning.billing.util.tag.DefaultTagDefinition;
 import com.ning.billing.util.tag.Tag;
 import com.ning.billing.util.tag.TagDefinition;
 import com.ning.billing.util.tag.api.TagEvent;
@@ -67,18 +69,42 @@ public class AuditedTagDao extends AuditedCollectionDaoBase<Tag, Tag> implements
         return obj;
     }
 
+    private TagDefinition getTagDefinitionFromTransaction(final TagSqlDao transTagSqlDao, final UUID tagDefinitionId)
+        throws TagApiException {
+
+        TagDefinition tagDefintion = null;
+        for (ControlTagType t : ControlTagType.values()) {
+            if (t.getId().equals(tagDefinitionId)) {
+                tagDefintion = new DefaultTagDefinition(t.getId(), t.toString(), t.getDescription(), true);
+                break;
+            }
+        }
+        if (tagDefintion == null) {
+            TagDefinitionSqlDao transTagDefintionSqlDao = tagSqlDao.become(TagDefinitionSqlDao.class);
+            tagDefintion = transTagDefintionSqlDao.getById(tagDefinitionId.toString());
+        }
+
+        if (tagDefintion == null) {
+            throw new TagApiException(ErrorCode.TAG_DEFINITION_DOES_NOT_EXIST, tagDefinitionId);
+        }
+        return tagDefintion;
+    }
+
+
     @Override
-    public void insertTag(final UUID objectId, final ObjectType objectType, final TagDefinition tagDefinition, final CallContext context) {
+    public void insertTag(final UUID objectId, final ObjectType objectType, final UUID tagDefinitionId, final CallContext context)
+     throws TagApiException {
         tagSqlDao.inTransaction(new Transaction<Void, TagSqlDao>() {
             @Override
-            public Void inTransaction(final TagSqlDao tagSqlDao, final TransactionStatus status) throws Exception {
+            public Void inTransaction(final TagSqlDao transTagSqlDao, final TransactionStatus status) throws Exception {
+
                 final String tagId = UUID.randomUUID().toString();
-                final String tagName = tagDefinition.getName();
+                final TagDefinition tagDefinition = getTagDefinitionFromTransaction(transTagSqlDao, tagDefinitionId);
 
                 // Create the tag
-                tagSqlDao.addTagFromTransaction(tagId, tagName, objectId.toString(), objectType, context);
+                tagSqlDao.addTagFromTransaction(tagId, tagDefinitionId.toString(), objectId.toString(), objectType, context);
 
-                final Tag tag = tagSqlDao.findTag(tagName, objectId.toString(), objectType);
+                final Tag tag = tagSqlDao.findTag(tagDefinitionId.toString(), objectId.toString(), objectType);
                 final List<Tag> tagList = Arrays.asList(tag);
 
                 // Gather the tag ids for this object id
@@ -108,23 +134,22 @@ public class AuditedTagDao extends AuditedCollectionDaoBase<Tag, Tag> implements
                 } catch (Bus.EventBusException e) {
                     log.warn("Failed to post tag creation event for tag " + tag.getId().toString(), e);
                 }
-
                 return null;
             }
         });
     }
 
     @Override
-    public void deleteTag(final UUID objectId, final ObjectType objectType, final TagDefinition tagDefinition, final CallContext context) throws TagApiException {
+    public void deleteTag(final UUID objectId, final ObjectType objectType, final UUID tagDefinitionId, 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);
+                public Void inTransaction(final TagSqlDao transTagSqlDao, final TransactionStatus status) throws Exception {
+
+                    final TagDefinition tagDefinition = getTagDefinitionFromTransaction(transTagSqlDao, tagDefinitionId);
+                    final Tag tag = tagSqlDao.findTag(tagDefinitionId.toString(), objectId.toString(), objectType);
                     if (tag == null) {
-                        throw new TagApiException(ErrorCode.TAG_DOES_NOT_EXIST, tagName);
+                        throw new TagApiException(ErrorCode.TAG_DOES_NOT_EXIST, tagDefinition.getName());
                     }
 
                     final List<Tag> tagList = Arrays.asList(tag);
@@ -189,6 +214,6 @@ public class AuditedTagDao extends AuditedCollectionDaoBase<Tag, Tag> implements
 
     @Override
     protected String getKey(final Tag entity) {
-        return entity.getTagDefinitionName();
+        return entity.getId().toString();
     }
 }
diff --git a/util/src/main/java/com/ning/billing/util/tag/dao/DefaultTagDefinitionDao.java b/util/src/main/java/com/ning/billing/util/tag/dao/DefaultTagDefinitionDao.java
index f7f25b7..582a384 100644
--- a/util/src/main/java/com/ning/billing/util/tag/dao/DefaultTagDefinitionDao.java
+++ b/util/src/main/java/com/ning/billing/util/tag/dao/DefaultTagDefinitionDao.java
@@ -16,8 +16,10 @@
 
 package com.ning.billing.util.tag.dao;
 
-import java.util.ArrayList;
+import java.util.Collection;
+import java.util.LinkedList;
 import java.util.List;
+import java.util.UUID;
 
 import org.skife.jdbi.v2.IDBI;
 import org.skife.jdbi.v2.Transaction;
@@ -26,6 +28,8 @@ import org.skife.jdbi.v2.exceptions.TransactionFailedException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.google.common.base.Function;
+import com.google.common.collect.Collections2;
 import com.google.inject.Inject;
 import com.ning.billing.ErrorCode;
 import com.ning.billing.util.api.TagDefinitionApiException;
@@ -54,27 +58,57 @@ public class DefaultTagDefinitionDao implements TagDefinitionDao {
     @Override
     public List<TagDefinition> getTagDefinitions() {
         // Get user definitions from the database
-        final List<TagDefinition> definitionList = new ArrayList<TagDefinition>();
+        final List<TagDefinition> definitionList = new LinkedList<TagDefinition>();
         definitionList.addAll(tagDefinitionSqlDao.get());
 
         // Add control tag definitions
         for (final ControlTagType controlTag : ControlTagType.values()) {
-            definitionList.add(new DefaultTagDefinition(controlTag.toString(), controlTag.getDescription(), true));
+            definitionList.add(new DefaultTagDefinition(controlTag.getId(), controlTag.toString(), controlTag.getDescription(), true));
         }
-
         return definitionList;
     }
 
     @Override
-    public TagDefinition getByName(final String definitionName) {
-        // Add control tag definitions
+    public TagDefinition getByName(String definitionName) {
+        for (final ControlTagType controlTag : ControlTagType.values()) {
+            if (controlTag.name().equals(definitionName)) {
+                return new DefaultTagDefinition(controlTag.getId(), controlTag.toString(), controlTag.getDescription(), true);
+            }
+         }
+        return tagDefinitionSqlDao.getByName(definitionName);
+    }
+
+
+    @Override
+    public TagDefinition getById(final UUID definitionId) {
         for (final ControlTagType controlTag : ControlTagType.values()) {
-            if (definitionName.equals(controlTag.name())) {
-                return new DefaultTagDefinition(controlTag.toString(), controlTag.getDescription(), true);
+            if (controlTag.getId().equals(definitionId)) {
+                return new DefaultTagDefinition(controlTag.getId(), controlTag.toString(), controlTag.getDescription(), true);
             }
         }
+        return tagDefinitionSqlDao.getById(definitionId.toString());
+    }
 
-        return tagDefinitionSqlDao.getByName(definitionName);
+    @Override
+    public List<TagDefinition> getByIds(final Collection<UUID> definitionIds) {
+
+        List<TagDefinition> result = new LinkedList<TagDefinition>();
+        for (final UUID cur : definitionIds) {
+            for (final ControlTagType controlTag : ControlTagType.values()) {
+                if (controlTag.getId().equals(cur)) {
+                    result.add(new DefaultTagDefinition(controlTag.getId(), controlTag.toString(), controlTag.getDescription(), true));
+                    break;
+                }
+            }
+        }
+
+        result.addAll(tagDefinitionSqlDao.getByIds(Collections2.transform(definitionIds, new Function<UUID, String>() {
+            @Override
+            public String apply(UUID input) {
+                return input.toString();
+            }
+        })));
+        return result;
     }
 
     @Override
@@ -135,24 +169,24 @@ public class DefaultTagDefinitionDao implements TagDefinitionDao {
     }
 
     @Override
-    public void deleteTagDefinition(final String definitionName, final CallContext context) throws TagDefinitionApiException {
+    public void deleteById(final UUID definitionId, final CallContext context) throws TagDefinitionApiException {
         try {
             tagDefinitionSqlDao.inTransaction(new Transaction<Void, TagDefinitionSqlDao>() {
                 @Override
                 public Void inTransaction(final TagDefinitionSqlDao tagDefinitionSqlDao, final TransactionStatus status) throws Exception {
                     // Make sure the tag definition exists
-                    final TagDefinition tagDefinition = tagDefinitionSqlDao.getByName(definitionName);
+                    final TagDefinition tagDefinition = tagDefinitionSqlDao.getById(definitionId.toString());
                     if (tagDefinition == null) {
-                        throw new TagDefinitionApiException(ErrorCode.TAG_DEFINITION_DOES_NOT_EXIST, definitionName);
+                        throw new TagDefinitionApiException(ErrorCode.TAG_DEFINITION_DOES_NOT_EXIST, definitionId);
                     }
 
                     // Make sure it is not used currently
-                    if (tagDefinitionSqlDao.tagDefinitionUsageCount(definitionName) > 0) {
-                        throw new TagDefinitionApiException(ErrorCode.TAG_DEFINITION_IN_USE, definitionName);
+                    if (tagDefinitionSqlDao.tagDefinitionUsageCount(definitionId.toString()) > 0) {
+                        throw new TagDefinitionApiException(ErrorCode.TAG_DEFINITION_IN_USE, definitionId);
                     }
 
                     // Delete it
-                    tagDefinitionSqlDao.deleteTagDefinition(definitionName, context);
+                    tagDefinitionSqlDao.deleteTagDefinition(definitionId.toString(), context);
 
                     // Post an event to the Bus
                     final TagDefinitionEvent tagDefinitionEvent;
diff --git a/util/src/main/java/com/ning/billing/util/tag/dao/TagBinder.java b/util/src/main/java/com/ning/billing/util/tag/dao/TagBinder.java
index d1a8a7c..4b310f3 100644
--- a/util/src/main/java/com/ning/billing/util/tag/dao/TagBinder.java
+++ b/util/src/main/java/com/ning/billing/util/tag/dao/TagBinder.java
@@ -34,11 +34,13 @@ import com.ning.billing.util.tag.Tag;
 @Target({ElementType.PARAMETER})
 public @interface TagBinder {
     public static class TagBinderFactory implements BinderFactory {
+        @Override
         public Binder build(final Annotation annotation) {
             return new Binder<TagBinder, Tag>() {
+                @Override
                 public void bind(final SQLStatement q, final TagBinder bind, final Tag tag) {
                     q.bind("id", tag.getId().toString());
-                    q.bind("tagDefinitionName", tag.getTagDefinitionName());
+                    q.bind("tagDefinitionId", tag.getTagDefinitionId().toString());
                 }
             };
         }
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 8db294a..c46c8e7 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
@@ -26,7 +26,7 @@ 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) throws TagApiException;
+    void insertTag(UUID objectId, ObjectType objectType, UUID tagDefinition, CallContext context) throws TagApiException;
 
-    void deleteTag(UUID objectId, ObjectType objectType, TagDefinition tagDefinition, CallContext context) throws TagApiException;
+    void deleteTag(UUID objectId, ObjectType objectType, UUID tagDefinition, CallContext context) throws TagApiException;
 }
diff --git a/util/src/main/java/com/ning/billing/util/tag/dao/TagDefinitionDao.java b/util/src/main/java/com/ning/billing/util/tag/dao/TagDefinitionDao.java
index ae645ea..72807a2 100644
--- a/util/src/main/java/com/ning/billing/util/tag/dao/TagDefinitionDao.java
+++ b/util/src/main/java/com/ning/billing/util/tag/dao/TagDefinitionDao.java
@@ -16,7 +16,9 @@
 
 package com.ning.billing.util.tag.dao;
 
+import java.util.Collection;
 import java.util.List;
+import java.util.UUID;
 
 import com.ning.billing.util.api.TagDefinitionApiException;
 import com.ning.billing.util.callcontext.CallContext;
@@ -25,9 +27,13 @@ import com.ning.billing.util.tag.TagDefinition;
 public interface TagDefinitionDao {
     public List<TagDefinition> getTagDefinitions();
 
-    public TagDefinition getByName(String definitionName);
+    public TagDefinition getById(final UUID definitionId);
 
-    public TagDefinition create(String definitionName, String description, CallContext context) throws TagDefinitionApiException;
+    public TagDefinition getByName(final String definitionName);
 
-    public void deleteTagDefinition(String definitionName, CallContext context) throws TagDefinitionApiException;
+    public List<TagDefinition> getByIds(final Collection<UUID> definitionIds);
+
+    public TagDefinition create(final String definitionName, final String description, final CallContext context) throws TagDefinitionApiException;
+
+    public void deleteById(final UUID definitionId, final CallContext context) throws TagDefinitionApiException;
 }
diff --git a/util/src/main/java/com/ning/billing/util/tag/dao/TagDefinitionSqlDao.java b/util/src/main/java/com/ning/billing/util/tag/dao/TagDefinitionSqlDao.java
index 6dee4b8..3256ba8 100644
--- a/util/src/main/java/com/ning/billing/util/tag/dao/TagDefinitionSqlDao.java
+++ b/util/src/main/java/com/ning/billing/util/tag/dao/TagDefinitionSqlDao.java
@@ -23,6 +23,8 @@ import java.lang.annotation.RetentionPolicy;
 import java.lang.annotation.Target;
 import java.sql.ResultSet;
 import java.sql.SQLException;
+import java.util.Collection;
+import java.util.List;
 import java.util.UUID;
 
 import org.skife.jdbi.v2.SQLStatement;
@@ -52,17 +54,17 @@ public interface TagDefinitionSqlDao extends EntitySqlDao<TagDefinition>, Transa
     @SqlUpdate
     public void create(@TagDefinitionBinder final TagDefinition entity, @CallContextBinder final CallContext context);
 
-    @SqlUpdate
-    public void deleteAllTagsForDefinition(@Bind("name") final String definitionName, @CallContextBinder final CallContext context);
+    @SqlQuery
+    public TagDefinition getByName(@Bind("name") final String definitionName);
 
     @SqlUpdate
-    public void deleteTagDefinition(@Bind("name") final String definitionName, @CallContextBinder final CallContext context);
+    public void deleteTagDefinition(@Bind("id") final String definitionId, @CallContextBinder final CallContext context);
 
     @SqlQuery
-    public int tagDefinitionUsageCount(@Bind("name") final String definitionName);
+    public int tagDefinitionUsageCount(@Bind("id") final String definitionId);
 
     @SqlQuery
-    public TagDefinition getByName(@Bind("name") final String definitionName);
+    public List<TagDefinition> getByIds(@UUIDCollectionBinder final Collection<String> definitionIds);
 
     public class TagDefinitionMapper implements ResultSetMapper<TagDefinition> {
         @Override
@@ -79,8 +81,10 @@ public interface TagDefinitionSqlDao extends EntitySqlDao<TagDefinition>, Transa
     @Target({ElementType.PARAMETER})
     public @interface TagDefinitionBinder {
         public static class TagDefinitionBinderFactory implements BinderFactory {
+            @Override
             public Binder build(final Annotation annotation) {
                 return new Binder<TagDefinitionBinder, TagDefinition>() {
+                    @Override
                     public void bind(final SQLStatement q, final TagDefinitionBinder bind, final TagDefinition tagDefinition) {
                         q.bind("id", tagDefinition.getId().toString());
                         q.bind("name", tagDefinition.getName());
diff --git a/util/src/main/java/com/ning/billing/util/tag/dao/TagHistoryBinder.java b/util/src/main/java/com/ning/billing/util/tag/dao/TagHistoryBinder.java
index b8cdded..11d279e 100644
--- a/util/src/main/java/com/ning/billing/util/tag/dao/TagHistoryBinder.java
+++ b/util/src/main/java/com/ning/billing/util/tag/dao/TagHistoryBinder.java
@@ -43,7 +43,7 @@ public @interface TagHistoryBinder {
                     q.bind("recordId", tagHistory.getValue());
                     q.bind("changeType", tagHistory.getChangeType().toString());
                     q.bind("id", tagHistory.getId().toString());
-                    q.bind("tagDefinitionName", tagHistory.getEntity().getTagDefinitionName());
+                    q.bind("tagDefinitionId", tagHistory.getEntity().getTagDefinitionId().toString());
                 }
             };
         }
diff --git a/util/src/main/java/com/ning/billing/util/tag/dao/TagMapper.java b/util/src/main/java/com/ning/billing/util/tag/dao/TagMapper.java
index da0083d..fe40e0d 100644
--- a/util/src/main/java/com/ning/billing/util/tag/dao/TagMapper.java
+++ b/util/src/main/java/com/ning/billing/util/tag/dao/TagMapper.java
@@ -32,18 +32,19 @@ import com.ning.billing.util.tag.Tag;
 public class TagMapper extends MapperBase implements ResultSetMapper<Tag> {
     @Override
     public Tag map(final int index, final ResultSet result, final StatementContext context) throws SQLException {
-        final String name = result.getString("tag_definition_name");
 
+        final UUID tagDefinitionId = getUUID(result, "tag_definition_id");
         ControlTagType thisTagType = null;
         for (final ControlTagType controlTagType : ControlTagType.values()) {
-            if (name.equals(controlTagType.toString())) {
+            if (tagDefinitionId.equals(controlTagType.getId())) {
                 thisTagType = controlTagType;
+                break;
             }
         }
 
-        final UUID id = UUID.fromString(result.getString("id"));
+        final UUID id = getUUID(result, "id");
         if (thisTagType == null) {
-            return new DescriptiveTag(id, name);
+            return new DescriptiveTag(id, tagDefinitionId);
         } else {
             return new DefaultControlTag(id, thisTagType);
         }
diff --git a/util/src/main/java/com/ning/billing/util/tag/dao/TagSqlDao.java b/util/src/main/java/com/ning/billing/util/tag/dao/TagSqlDao.java
index 5f4b8bb..23bdce6 100644
--- a/util/src/main/java/com/ning/billing/util/tag/dao/TagSqlDao.java
+++ b/util/src/main/java/com/ning/billing/util/tag/dao/TagSqlDao.java
@@ -69,19 +69,19 @@ public interface TagSqlDao extends UpdatableEntityCollectionSqlDao<Tag>, Transac
 
     @SqlUpdate
     public void addTagFromTransaction(@Bind("id") final String tagId,
-                                      @Bind("tagDefinitionName") final String tagName,
+                                      @Bind("tagDefinitionId") final String tagDefinitionId,
                                       @Bind("objectId") final String objectId,
                                       @ObjectTypeBinder final ObjectType objectType,
                                       @CallContextBinder final CallContext context);
 
     @SqlUpdate
-    public void removeTagFromTransaction(@Bind("tagDefinitionName") final String tagName,
+    public void removeTagFromTransaction(@Bind("tagDefinitionId") final String tagDefinitionId,
                                          @Bind("objectId") final String objectId,
                                          @ObjectTypeBinder final ObjectType objectType,
                                          @CallContextBinder final CallContext context);
 
     @SqlQuery
-    public Tag findTag(@Bind("tagDefinitionName") final String tagName,
+    public Tag findTag(@Bind("tagDefinitionId") final String tagDefinitionId,
                        @Bind("objectId") final String objectId,
                        @ObjectTypeBinder final ObjectType objectType);
 }
diff --git a/util/src/main/java/com/ning/billing/util/tag/dao/UUIDCollectionBinder.java b/util/src/main/java/com/ning/billing/util/tag/dao/UUIDCollectionBinder.java
new file mode 100644
index 0000000..7cd131c
--- /dev/null
+++ b/util/src/main/java/com/ning/billing/util/tag/dao/UUIDCollectionBinder.java
@@ -0,0 +1,55 @@
+/*
+ * 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.util.tag.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.util.Collection;
+import java.util.List;
+
+import org.skife.jdbi.v2.SQLStatement;
+import org.skife.jdbi.v2.sqlobject.Binder;
+import org.skife.jdbi.v2.sqlobject.BinderFactory;
+import org.skife.jdbi.v2.sqlobject.BindingAnnotation;
+
+
+@BindingAnnotation(UUIDCollectionBinder.UUIDCollectionBinderFactory.class)
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.PARAMETER})
+public @interface UUIDCollectionBinder {
+    public static class UUIDCollectionBinderFactory implements BinderFactory {
+        @Override
+        public Binder build(Annotation annotation) {
+            return new Binder<UUIDCollectionBinder, Collection<String>>() {
+
+                @Override
+                public void bind(SQLStatement<?> query, UUIDCollectionBinder bind, Collection<String> ids) {
+                    query.define("tag_definition_ids", ids);
+
+                    int idx = 0;
+                    for (String id : ids) {
+                        query.bind("id_" + idx, id);
+                        idx++;
+                    }
+
+                }
+            };
+        }
+    }
+}
diff --git a/util/src/main/java/com/ning/billing/util/tag/DefaultControlTag.java b/util/src/main/java/com/ning/billing/util/tag/DefaultControlTag.java
index 20efa9c..c9b624f 100644
--- a/util/src/main/java/com/ning/billing/util/tag/DefaultControlTag.java
+++ b/util/src/main/java/com/ning/billing/util/tag/DefaultControlTag.java
@@ -23,13 +23,13 @@ public class DefaultControlTag extends DescriptiveTag implements ControlTag {
 
     // use to create new objects
     public DefaultControlTag(final ControlTagType controlTagType) {
-        super(controlTagType.toString());
+        super(controlTagType.getId());
         this.controlTagType = controlTagType;
     }
 
     // use to hydrate objects when loaded from the persistence layer
     public DefaultControlTag(final UUID id, final ControlTagType controlTagType) {
-        super(id, controlTagType.toString());
+        super(id, controlTagType.getId());
         this.controlTagType = controlTagType;
     }
 
diff --git a/util/src/main/java/com/ning/billing/util/tag/DefaultTagDefinition.java b/util/src/main/java/com/ning/billing/util/tag/DefaultTagDefinition.java
index f0e80ad..3e566a5 100644
--- a/util/src/main/java/com/ning/billing/util/tag/DefaultTagDefinition.java
+++ b/util/src/main/java/com/ning/billing/util/tag/DefaultTagDefinition.java
@@ -68,6 +68,8 @@ public class DefaultTagDefinition extends EntityBase implements TagDefinition {
         return sb.toString();
     }
 
+
+
     @Override
     public boolean equals(final Object o) {
         if (this == o) {
@@ -76,9 +78,11 @@ public class DefaultTagDefinition extends EntityBase implements TagDefinition {
         if (o == null || getClass() != o.getClass()) {
             return false;
         }
-
         final DefaultTagDefinition that = (DefaultTagDefinition) o;
 
+        if (id != null ? !id.equals(that.id) : that.id != null) {
+            return false;
+        }
         if (description != null ? !description.equals(that.description) : that.description != null) {
             return false;
         }
@@ -88,13 +92,13 @@ public class DefaultTagDefinition extends EntityBase implements TagDefinition {
         if (name != null ? !name.equals(that.name) : that.name != null) {
             return false;
         }
-
         return true;
     }
 
     @Override
     public int hashCode() {
         int result = name != null ? name.hashCode() : 0;
+        result = 31 * result + (id != null ? id.hashCode() : 0);
         result = 31 * result + (description != null ? description.hashCode() : 0);
         result = 31 * result + (controlTag != null ? controlTag.hashCode() : 0);
         return result;
diff --git a/util/src/main/java/com/ning/billing/util/tag/DefaultTagStore.java b/util/src/main/java/com/ning/billing/util/tag/DefaultTagStore.java
index 8bbe9e8..0388dda 100644
--- a/util/src/main/java/com/ning/billing/util/tag/DefaultTagStore.java
+++ b/util/src/main/java/com/ning/billing/util/tag/DefaultTagStore.java
@@ -28,7 +28,7 @@ public class DefaultTagStore extends EntityCollectionBase<Tag> implements TagSto
 
     @Override
     public String getEntityKey(final Tag entity) {
-        return entity.getTagDefinitionName();
+        return entity.getTagDefinitionId().toString();
     }
 
     @Override
@@ -71,7 +71,7 @@ public class DefaultTagStore extends EntityCollectionBase<Tag> implements TagSto
     @Override
     public boolean containsTagForDefinition(final TagDefinition tagDefinition) {
         for (final Tag tag : entities.values()) {
-            if (tag.getTagDefinitionName().equals(tagDefinition.getName())) {
+            if (tag.getTagDefinitionId().equals(tagDefinition.getId())) {
                 return true;
             }
         }
@@ -82,7 +82,7 @@ public class DefaultTagStore extends EntityCollectionBase<Tag> implements TagSto
     @Override
     public boolean containsTagForControlTagType(final ControlTagType controlTagType) {
         for (final Tag tag : entities.values()) {
-            if (tag.getTagDefinitionName().equals(controlTagType.toString())) {
+            if (tag.getTagDefinitionId().equals(controlTagType.getId())) {
                 return true;
             }
         }
diff --git a/util/src/main/java/com/ning/billing/util/tag/DescriptiveTag.java b/util/src/main/java/com/ning/billing/util/tag/DescriptiveTag.java
index 7c87e7b..772d391 100644
--- a/util/src/main/java/com/ning/billing/util/tag/DescriptiveTag.java
+++ b/util/src/main/java/com/ning/billing/util/tag/DescriptiveTag.java
@@ -21,42 +21,39 @@ import java.util.UUID;
 import com.ning.billing.util.entity.EntityBase;
 
 public class DescriptiveTag extends EntityBase implements Tag {
-    private final String tagDefinitionName;
+
+    private final UUID tagDefinitionId;
 
     // use to hydrate objects from the persistence layer
-    public DescriptiveTag(final UUID id, final String tagDefinitionName) {
+    public DescriptiveTag(final UUID id, final UUID tagDefinitionId) {
         super(id);
-        this.tagDefinitionName = tagDefinitionName;
+        this.tagDefinitionId = tagDefinitionId;
     }
 
     // use to create new objects
-    public DescriptiveTag(final TagDefinition tagDefinition) {
+    public DescriptiveTag(final UUID tagDefinitionId) {
         super();
-        this.tagDefinitionName = tagDefinition.getName();
+        this.tagDefinitionId = tagDefinitionId;
     }
 
-    // use to create new objects
-    public DescriptiveTag(final String tagDefinitionName) {
-        super();
-        this.tagDefinitionName = tagDefinitionName;
-    }
 
     @Override
-    public String getTagDefinitionName() {
-        return tagDefinitionName;
+    public UUID getTagDefinitionId() {
+        return tagDefinitionId;
     }
 
+
     @Override
     public String toString() {
-        return "DescriptiveTag [tagDefinitionName=" + tagDefinitionName + ", id=" + id + "]";
+        return "DescriptiveTag [tagDefinitionId=" + tagDefinitionId + ", id=" + id + "]";
     }
 
     @Override
     public int hashCode() {
         final int prime = 31;
         int result = 1;
-        result = prime * result + ((tagDefinitionName == null) ? 0
-                : tagDefinitionName.hashCode());
+        result = prime * result + ((tagDefinitionId == null) ? 0
+                : tagDefinitionId.hashCode());
         return result;
     }
 
@@ -72,11 +69,11 @@ public class DescriptiveTag extends EntityBase implements Tag {
             return false;
         }
         final DescriptiveTag other = (DescriptiveTag) obj;
-        if (tagDefinitionName == null) {
-            if (other.tagDefinitionName != null) {
+        if (tagDefinitionId == null) {
+            if (other.tagDefinitionId != null) {
                 return false;
             }
-        } else if (!tagDefinitionName.equals(other.tagDefinitionName)) {
+        } else if (!tagDefinitionId.equals(other.tagDefinitionId)) {
             return false;
         }
         return true;
diff --git a/util/src/main/resources/com/ning/billing/util/ddl.sql b/util/src/main/resources/com/ning/billing/util/ddl.sql
index b7a00f9..8fe1028 100644
--- a/util/src/main/resources/com/ning/billing/util/ddl.sql
+++ b/util/src/main/resources/com/ning/billing/util/ddl.sql
@@ -75,7 +75,7 @@ DROP TABLE IF EXISTS tags;
 CREATE TABLE tags (
     record_id int(11) unsigned NOT NULL AUTO_INCREMENT,
     id char(36) NOT NULL,
-    tag_definition_name varchar(20) NOT NULL,
+    tag_definition_id char(36) NOT NULL,
     object_id char(36) NOT NULL,
     object_type varchar(30) NOT NULL,
     created_by varchar(50) NOT NULL,
@@ -86,7 +86,7 @@ CREATE TABLE tags (
 ) ENGINE = innodb;
 CREATE UNIQUE INDEX tags_id ON tags(id);
 CREATE INDEX tags_by_object ON tags(object_id);
-CREATE UNIQUE INDEX tags_unique ON tags(tag_definition_name, object_id);
+CREATE UNIQUE INDEX tags_unique ON tags(tag_definition_id, object_id);
 
 DROP TABLE IF EXISTS tag_history;
 CREATE TABLE tag_history (
@@ -95,7 +95,7 @@ CREATE TABLE tag_history (
     id char(36) NOT NULL,
     object_id char(36) NOT NULL,
     object_type varchar(30) NOT NULL,
-    tag_definition_name varchar(20) NOT NULL,
+    tag_definition_id char(36) NOT NULL,
     updated_by varchar(50) NOT NULL,
     date datetime NOT NULL,
     change_type char(6) NOT NULL,
diff --git a/util/src/main/resources/com/ning/billing/util/tag/dao/TagDefinitionSqlDao.sql.stg b/util/src/main/resources/com/ning/billing/util/tag/dao/TagDefinitionSqlDao.sql.stg
index 2a03325..832bb17 100644
--- a/util/src/main/resources/com/ning/billing/util/tag/dao/TagDefinitionSqlDao.sql.stg
+++ b/util/src/main/resources/com/ning/billing/util/tag/dao/TagDefinitionSqlDao.sql.stg
@@ -26,27 +26,33 @@ load() ::= <<
   WHERE id = :id;
 >>
 
-deleteAllTagsForDefinition() ::= <<
-  DELETE FROM tags
-  WHERE tag_definition_name = :name;
->>
 
 deleteTagDefinition() ::= <<
   DELETE FROM tag_definitions
-  WHERE name = :name;
+  WHERE id = :id;
 >>
 
 tagDefinitionUsageCount() ::= <<
   SELECT COUNT(id)
   FROM tags
-  WHERE tag_definition_name = :name
+  WHERE tag_definition_id = :id
 >>
 
 getByName() ::= <<
   SELECT <fields()>
-  FROM tag_definitions
+   FROM tag_definitions
   WHERE name = :name;
 >>
-;
 
+getById() ::= <<
+  SELECT <fields()>
+  FROM tag_definitions
+  WHERE id = :id;
+>>
 
+getByIds(tag_definition_ids) ::= <<
+  SELECT <fields()>
+  FROM tag_definitions
+  WHERE id IN (<tag_definition_ids: {id | :id_<i0>}; separator="," >)
+>>
+;
diff --git a/util/src/main/resources/com/ning/billing/util/tag/dao/TagSqlDao.sql.stg b/util/src/main/resources/com/ning/billing/util/tag/dao/TagSqlDao.sql.stg
index 1b994af..e80ada7 100644
--- a/util/src/main/resources/com/ning/billing/util/tag/dao/TagSqlDao.sql.stg
+++ b/util/src/main/resources/com/ning/billing/util/tag/dao/TagSqlDao.sql.stg
@@ -2,7 +2,7 @@ group TagDao;
 
 fields(prefix) ::= <<
     <prefix>id,
-    <prefix>tag_definition_name,
+    <prefix>tag_definition_id,
     <prefix>object_id,
     <prefix>object_type,
     <prefix>created_by,
@@ -11,43 +11,32 @@ fields(prefix) ::= <<
 
 insertFromTransaction() ::= <<
   INSERT INTO tags(<fields()>)
-  VALUES (:id, :tagDefinitionName, :objectId, :objectType, :userName, :createdDate);
+  VALUES (:id, :tagDefinitionId, :objectId, :objectType, :userName, :createdDate);
 >>
 
 deleteFromTransaction() ::= <<
     DELETE FROM tags
-    WHERE tag_definition_name = :tagDefinitionName
+    WHERE tag_definition_id = :tagDefinitionId
         AND object_id = :objectId AND object_type = :objectType;
 >>
 
 addTagFromTransaction() ::= <<
     INSERT INTO tags(<fields()>)
-    VALUES (:id, :tagDefinitionName, :objectId, :objectType, :userName, :createdDate);
+    VALUES (:id, :tagDefinitionId, :objectId, :objectType, :userName, :createdDate);
 >>
 
 removeTagFromTransaction() ::= <<
     DELETE FROM tags
-    WHERE tag_definition_name = :tagDefinitionName
+    WHERE tag_definition_id = :tagDefinitionId
     AND object_id = :objectId AND object_type = :objectType;
 >>
 
 findTag() ::= <<
-    SELECT <fields()>   FROM tags
-    WHERE tag_definition_name = :tagDefinitionName
+    SELECT <fields()> FROM tags
+    WHERE tag_definition_id = :tagDefinitionId
     AND object_id = :objectId AND object_type = :objectType;
 >>
 
-load() ::= <<
-    SELECT t.id, t.object_id, t.object_type, t.created_by, t.created_date,
-           td.id AS tag_definition_id,
-           t.tag_definition_name AS tag_definition_name,
-           td.description AS tag_description,
-           td.created_by
-    FROM tags t
-    LEFT JOIN tag_definitions td ON t.tag_definition_name = td.name
-    WHERE t.object_id = :objectId AND t.object_type = :objectType;
->>
-
 getRecordIds() ::= <<
     SELECT record_id, id
     FROM tags
@@ -59,7 +48,7 @@ historyFields(prefix) ::= <<
   <prefix>id,
   <prefix>object_id,
   <prefix>object_type,
-  <prefix>tag_definition_name,
+  <prefix>tag_definition_id,
   <prefix>updated_by,
   <prefix>date,
   <prefix>change_type
@@ -67,7 +56,7 @@ historyFields(prefix) ::= <<
 
 addHistoryFromTransaction() ::= <<
     INSERT INTO tag_history(<historyFields()>)
-    VALUES(:recordId, :id, :objectId, :objectType, :tagDefinitionName, :userName, :updatedDate, :changeType);
+    VALUES(:recordId, :id, :objectId, :objectType, :tagDefinitionId, :userName, :updatedDate, :changeType);
 >>
 
 getMaxHistoryRecordId() ::= <<
@@ -92,6 +81,12 @@ auditFields(prefix) ::= <<
     <prefix>user_token
 >>
 
+load() ::= <<
+  SELECT <fields()>
+    FROM tags
+  WHERE object_id = :objectId AND object_type = :objectType;
+>>
+
 insertAuditFromTransaction() ::= <<
     INSERT INTO audit_log(<auditFields()>)
     VALUES(:tableName, :recordId, :changeType, :createdDate, :userName, :reasonCode, :comment, :userToken);
diff --git a/util/src/test/java/com/ning/billing/util/tag/dao/MockTagDao.java b/util/src/test/java/com/ning/billing/util/tag/dao/MockTagDao.java
index a09a952..705966e 100644
--- a/util/src/test/java/com/ning/billing/util/tag/dao/MockTagDao.java
+++ b/util/src/test/java/com/ning/billing/util/tag/dao/MockTagDao.java
@@ -59,7 +59,7 @@ public class MockTagDao implements TagDao {
         final Map<String, Tag> map = new HashMap<String, Tag>();
         if (tags != null) {
             for (final Tag tag : tags) {
-                map.put(tag.getTagDefinitionName(), tag);
+                map.put(tag.getTagDefinitionId().toString(), tag);
             }
         }
         return map;
@@ -67,13 +67,13 @@ public class MockTagDao implements TagDao {
 
     @Override
     public void insertTag(final UUID objectId, final ObjectType objectType,
-                          final TagDefinition tagDefinition, final CallContext context) {
+                          final UUID tagDefinitionId, final CallContext context) {
         final Tag tag = new Tag() {
             private final UUID id = UUID.randomUUID();
 
             @Override
-            public String getTagDefinitionName() {
-                return tagDefinition.getName();
+            public UUID getTagDefinitionId() {
+                return tagDefinitionId;
             }
 
             @Override
@@ -91,13 +91,13 @@ public class MockTagDao implements TagDao {
 
     @Override
     public void deleteTag(final UUID objectId, final ObjectType objectType,
-                          final TagDefinition tagDefinition, final CallContext context) {
+                          final UUID tagDefinitionId, final CallContext context) {
         final List<Tag> tags = tagStore.get(objectId);
         if (tags != null) {
             final Iterator<Tag> tagIterator = tags.iterator();
             while (tagIterator.hasNext()) {
                 final Tag tag = tagIterator.next();
-                if (tag.getTagDefinitionName().equals(tagDefinition.getName())) {
+                if (tag.getTagDefinitionId().equals(tagDefinitionId)) {
                     tagIterator.remove();
                 }
             }
diff --git a/util/src/test/java/com/ning/billing/util/tag/dao/MockTagDefinitionDao.java b/util/src/test/java/com/ning/billing/util/tag/dao/MockTagDefinitionDao.java
index d7a3e63..b1a1b5d 100644
--- a/util/src/test/java/com/ning/billing/util/tag/dao/MockTagDefinitionDao.java
+++ b/util/src/test/java/com/ning/billing/util/tag/dao/MockTagDefinitionDao.java
@@ -17,8 +17,10 @@
 package com.ning.billing.util.tag.dao;
 
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.List;
 import java.util.Map;
+import java.util.UUID;
 import java.util.concurrent.ConcurrentHashMap;
 
 import com.ning.billing.util.api.TagDefinitionApiException;
@@ -44,12 +46,22 @@ public class MockTagDefinitionDao implements TagDefinitionDao {
                                 final CallContext context) throws TagDefinitionApiException {
         final TagDefinition tag = new DefaultTagDefinition(definitionName, description, false);
 
-        tags.put(definitionName, tag);
+        tags.put(tag.getId().toString(), tag);
         return tag;
     }
 
     @Override
-    public void deleteTagDefinition(final String definitionName, final CallContext context) throws TagDefinitionApiException {
-        tags.remove(definitionName);
+    public void deleteById(final UUID definitionId, final CallContext context) throws TagDefinitionApiException {
+        tags.remove(definitionId.toString());
+    }
+
+    @Override
+    public TagDefinition getById(UUID definitionId) {
+        return null;
+    }
+
+    @Override
+    public List<TagDefinition> getByIds(Collection<UUID> definitionIds) {
+        return null;
     }
 }
diff --git a/util/src/test/java/com/ning/billing/util/tag/dao/TestAuditedTagDao.java b/util/src/test/java/com/ning/billing/util/tag/dao/TestAuditedTagDao.java
index 35c3117..cd0e544 100644
--- a/util/src/test/java/com/ning/billing/util/tag/dao/TestAuditedTagDao.java
+++ b/util/src/test/java/com/ning/billing/util/tag/dao/TestAuditedTagDao.java
@@ -16,6 +16,8 @@
 
 package com.ning.billing.util.tag.dao;
 
+import static org.testng.Assert.assertEquals;
+
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
@@ -33,6 +35,7 @@ import com.google.common.eventbus.Subscribe;
 import com.google.inject.Inject;
 import com.ning.billing.dbi.MysqlTestingHelper;
 import com.ning.billing.util.UtilTestSuiteWithEmbeddedDB;
+import com.ning.billing.util.api.TagDefinitionApiException;
 import com.ning.billing.util.bus.Bus;
 import com.ning.billing.util.bus.BusEvent;
 import com.ning.billing.util.callcontext.CallContext;
@@ -42,6 +45,7 @@ import com.ning.billing.util.callcontext.UserType;
 import com.ning.billing.util.clock.Clock;
 import com.ning.billing.util.dao.ObjectType;
 import com.ning.billing.util.io.IOUtils;
+import com.ning.billing.util.tag.ControlTagType;
 import com.ning.billing.util.tag.MockTagStoreModuleSql;
 import com.ning.billing.util.tag.Tag;
 import com.ning.billing.util.tag.TagDefinition;
@@ -85,6 +89,73 @@ public class TestAuditedTagDao extends UtilTestSuiteWithEmbeddedDB {
         bus.stop();
     }
 
+
+    @Test(groups= {"slow"})
+    public void testGetByIds() throws TagDefinitionApiException {
+
+        final List<UUID> uuids = new ArrayList<UUID>();
+
+        TagDefinition defYo = tagDefinitionDao.create("yo", "defintion yo", context);
+        uuids.add(defYo.getId());
+        TagDefinition defBah = tagDefinitionDao.create("bah", "defintion bah", context);
+        uuids.add(defBah.getId());
+        TagDefinition defZoo = tagDefinitionDao.create("zoo", "defintion zoo", context);
+        uuids.add(defZoo.getId());
+
+        List<TagDefinition> result = tagDefinitionDao.getByIds(uuids);
+        assertEquals(result.size(), 3);
+
+        // Add control tag and retry
+        uuids.add(ControlTagType.AUTO_PAY_OFF.getId());
+        result = tagDefinitionDao.getByIds(uuids);
+        assertEquals(result.size(), 4);
+
+        result = tagDefinitionDao.getTagDefinitions();
+        assertEquals(result.size(), 7);
+    }
+
+    @Test(groups= {"slow"})
+    public void testGetById() throws TagDefinitionApiException {
+
+        // User Tag
+        TagDefinition defYo = tagDefinitionDao.create("yo", "defintion yo", context);
+        TagDefinition resDefYo = tagDefinitionDao.getById(defYo.getId());
+        assertEquals(defYo, resDefYo);
+
+        // Control Tag
+        try {
+            tagDefinitionDao.create(ControlTagType.AUTO_INVOICING_OFF.name(), ControlTagType.AUTO_INVOICING_OFF.name(), context);
+            Assert.fail("Should not be able to create a control tag");
+        } catch (TagDefinitionApiException ignore) {
+        }
+        TagDefinition resdef_AUTO_INVOICING_OFF = tagDefinitionDao.getById(ControlTagType.AUTO_INVOICING_OFF.getId());
+        assertEquals(resdef_AUTO_INVOICING_OFF.getId(), ControlTagType.AUTO_INVOICING_OFF.getId());
+        assertEquals(resdef_AUTO_INVOICING_OFF.getName(), ControlTagType.AUTO_INVOICING_OFF.name());
+        assertEquals(resdef_AUTO_INVOICING_OFF.getDescription(), ControlTagType.AUTO_INVOICING_OFF.getDescription());
+    }
+
+    @Test(groups= {"slow"})
+    public void testGetByName() throws TagDefinitionApiException {
+
+        // User Tag
+        TagDefinition defYo = tagDefinitionDao.create("yo", "defintion yo", context);
+        TagDefinition resDefYo = tagDefinitionDao.getByName(defYo.getName());
+        assertEquals(defYo, resDefYo);
+
+        // Control Tag
+        try {
+            tagDefinitionDao.create(ControlTagType.AUTO_PAY_OFF.name(), ControlTagType.AUTO_INVOICING_OFF.name(), context);
+            Assert.fail("Should not be able to create a control tag");
+        } catch (TagDefinitionApiException ignore) {
+        }
+        TagDefinition resdef_AUTO_PAY_OFF = tagDefinitionDao.getByName(ControlTagType.AUTO_PAY_OFF.name());
+        assertEquals(resdef_AUTO_PAY_OFF.getId(), ControlTagType.AUTO_PAY_OFF.getId());
+        assertEquals(resdef_AUTO_PAY_OFF.getName(), ControlTagType.AUTO_PAY_OFF.name());
+        assertEquals(resdef_AUTO_PAY_OFF.getDescription(), ControlTagType.AUTO_PAY_OFF.getDescription());
+    }
+
+
+
     @Test(groups = "slow")
     public void testCatchEventsOnCreateAndDelete() throws Exception {
         final String definitionName = UUID.randomUUID().toString().substring(0, 5);
@@ -102,12 +173,12 @@ public class TestAuditedTagDao extends UtilTestSuiteWithEmbeddedDB {
         Assert.assertEquals(createdTagDefinition.getDescription(), description);
 
         // Make sure we can create a tag
-        tagDao.insertTag(objectId, objectType, createdTagDefinition, context);
+        tagDao.insertTag(objectId, objectType, createdTagDefinition.getId(), context);
 
         // Make sure we can retrieve it via the DAO
         final Map<String, Tag> foundTags = tagDao.loadEntities(objectId, objectType);
         Assert.assertEquals(foundTags.keySet().size(), 1);
-        Assert.assertEquals(foundTags.get(definitionName).getTagDefinitionName(), definitionName);
+        Assert.assertEquals(foundTags.values().iterator().next().getTagDefinitionId(), createdTagDefinition.getId());
 
         // Verify we caught an event on the bus -  we got 2 total (one for the tag definition, one for the tag)
         Assert.assertEquals(eventsListener.getEvents().size(), 2);
@@ -122,7 +193,7 @@ public class TestAuditedTagDao extends UtilTestSuiteWithEmbeddedDB {
         Assert.assertEquals(tagFirstEventReceived.getUserToken(), context.getUserToken());
 
         // Delete the tag
-        tagDao.deleteTag(objectId, objectType, createdTagDefinition, context);
+        tagDao.deleteTag(objectId, objectType, createdTagDefinition.getId(), context);
 
         // Make sure the tag is deleted
         Assert.assertEquals(tagDao.loadEntities(objectId, objectType).keySet().size(), 0);
diff --git a/util/src/test/java/com/ning/billing/util/tag/dao/TestDefaultTagDefinitionDao.java b/util/src/test/java/com/ning/billing/util/tag/dao/TestDefaultTagDefinitionDao.java
index 15d00e1..90d1abc 100644
--- a/util/src/test/java/com/ning/billing/util/tag/dao/TestDefaultTagDefinitionDao.java
+++ b/util/src/test/java/com/ning/billing/util/tag/dao/TestDefaultTagDefinitionDao.java
@@ -108,7 +108,7 @@ public class TestDefaultTagDefinitionDao extends UtilTestSuiteWithEmbeddedDB {
         Assert.assertEquals(tagDefinitionFirstEventReceived.getUserToken(), context.getUserToken());
 
         // Delete the tag definition
-        tagDefinitionDao.deleteTagDefinition(definitionName, context);
+        tagDefinitionDao.deleteById(foundTagDefinition.getId(), context);
 
         // Make sure the tag definition is deleted
         Assert.assertNull(tagDefinitionDao.getByName(definitionName));
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 0fb9e97..36ecd36 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
@@ -106,7 +106,7 @@ public class TestTagStore extends UtilTestSuiteWithEmbeddedDB {
         final UUID accountId = UUID.randomUUID();
 
         final TagStore tagStore = new DefaultTagStore(accountId, ObjectType.ACCOUNT);
-        final Tag tag = new DescriptiveTag(testTag);
+        final Tag tag = new DescriptiveTag(testTag.getId());
         tagStore.add(tag);
 
         tagDao.saveEntities(accountId, ObjectType.ACCOUNT, tagStore.getEntityList(), context);
@@ -114,8 +114,8 @@ public class TestTagStore extends UtilTestSuiteWithEmbeddedDB {
         final Map<String, Tag> savedTags = tagDao.loadEntities(accountId, ObjectType.ACCOUNT);
         assertEquals(savedTags.size(), 1);
 
-        final Tag savedTag = savedTags.get(tag.getTagDefinitionName());
-        assertEquals(savedTag.getTagDefinitionName(), tag.getTagDefinitionName());
+        final Tag savedTag = savedTags.get(tag.getId().toString());
+        assertEquals(savedTag.getTagDefinitionId(), tag.getTagDefinitionId());
         assertEquals(savedTag.getId(), tag.getId());
     }
 
@@ -138,7 +138,7 @@ public class TestTagStore extends UtilTestSuiteWithEmbeddedDB {
         final Map<String, Tag> tagMap = tagDao.loadEntities(accountId, ObjectType.ACCOUNT);
         assertEquals(tagMap.size(), 1);
 
-        assertEquals(tagMap.containsKey(ControlTagType.AUTO_INVOICING_OFF.toString()), true);
+        assertEquals(tagMap.values().iterator().next().getTagDefinitionId(), ControlTagType.AUTO_INVOICING_OFF.getId());
     }
 
     @Test(groups = "slow")
@@ -154,7 +154,7 @@ public class TestTagStore extends UtilTestSuiteWithEmbeddedDB {
             fail("Tag definition creation failed.", e);
         }
 
-        final DescriptiveTag tag = new DescriptiveTag(tagDefinition);
+        final DescriptiveTag tag = new DescriptiveTag(tagDefinition.getId());
         tagStore.add(tag);
         assertEquals(tagStore.generateInvoice(), true);
 
@@ -166,7 +166,7 @@ public class TestTagStore extends UtilTestSuiteWithEmbeddedDB {
         final Map<String, Tag> tagMap = tagDao.loadEntities(accountId, ObjectType.ACCOUNT);
         assertEquals(tagMap.size(), 1);
 
-        assertEquals(tagMap.containsKey(ControlTagType.AUTO_INVOICING_OFF.toString()), false);
+        assertEquals(tagMap.values().iterator().next().getTagDefinitionId(), tagDefinition.getId());
     }
 
     @Test(groups = "slow")
@@ -182,7 +182,7 @@ public class TestTagStore extends UtilTestSuiteWithEmbeddedDB {
             fail("Tag definition creation failed.", e);
         }
 
-        final DescriptiveTag descriptiveTag = new DescriptiveTag(tagDefinition);
+        final DescriptiveTag descriptiveTag = new DescriptiveTag(tagDefinition.getId());
         tagStore.add(descriptiveTag);
         assertEquals(tagStore.generateInvoice(), true);
 
@@ -198,7 +198,15 @@ public class TestTagStore extends UtilTestSuiteWithEmbeddedDB {
         final Map<String, Tag> tagMap = tagDao.loadEntities(accountId, ObjectType.ACCOUNT);
         assertEquals(tagMap.size(), 2);
 
-        assertEquals(tagMap.containsKey(ControlTagType.AUTO_INVOICING_OFF.toString()), true);
+        boolean found_AUTO_INVOICING_OFF_tag = false;
+        for (Tag cur : tagMap.values()) {
+            if (cur.getTagDefinitionId().equals(ControlTagType.AUTO_INVOICING_OFF.getId())) {
+                found_AUTO_INVOICING_OFF_tag = true;
+                break;
+            }
+        }
+        assertEquals(found_AUTO_INVOICING_OFF_tag, true);
+
     }
 
     @Test(groups = "slow")
@@ -233,7 +241,7 @@ public class TestTagStore extends UtilTestSuiteWithEmbeddedDB {
         TagDefinition tagDefinition = tagDefinitionDao.getByName(definitionName);
         assertNotNull(tagDefinition);
 
-        tagDefinitionDao.deleteTagDefinition(definitionName, context);
+        tagDefinitionDao.deleteById(tagDefinition.getId(), context);
         tagDefinition = tagDefinitionDao.getByName(definitionName);
         assertNull(tagDefinition);
     }
@@ -248,7 +256,7 @@ public class TestTagStore extends UtilTestSuiteWithEmbeddedDB {
 
         final UUID objectId = UUID.randomUUID();
         final TagStore tagStore = new DefaultTagStore(objectId, ObjectType.ACCOUNT);
-        final Tag tag = new DescriptiveTag(tagDefinition);
+        final Tag tag = new DescriptiveTag(tagDefinition.getId());
         tagStore.add(tag);
 
         tagDao.saveEntities(objectId, ObjectType.ACCOUNT, tagStore.getEntityList(), context);
@@ -256,7 +264,7 @@ public class TestTagStore extends UtilTestSuiteWithEmbeddedDB {
         final Map<String, Tag> tagMap = tagDao.loadEntities(objectId, ObjectType.ACCOUNT);
         assertEquals(tagMap.size(), 1);
 
-        tagDefinitionDao.deleteTagDefinition(definitionName, context);
+        tagDefinitionDao.deleteById(tagDefinition.getId(), context);
     }
 
     @Test(groups = "slow")
@@ -273,7 +281,7 @@ public class TestTagStore extends UtilTestSuiteWithEmbeddedDB {
 
         final UUID objectId = UUID.randomUUID();
         final TagStore tagStore = new DefaultTagStore(objectId, ObjectType.ACCOUNT);
-        final Tag tag = new DescriptiveTag(tagDefinition);
+        final Tag tag = new DescriptiveTag(tagDefinition.getId());
         tagStore.add(tag);
 
         tagDao.saveEntities(objectId, ObjectType.ACCOUNT, tagStore.getEntityList(), context);
@@ -281,12 +289,12 @@ public class TestTagStore extends UtilTestSuiteWithEmbeddedDB {
         final Map<String, Tag> tagMap = tagDao.loadEntities(objectId, ObjectType.ACCOUNT);
         assertEquals(tagMap.size(), 1);
 
-        tagDao.deleteTag(objectId, ObjectType.ACCOUNT, tagDefinition, context);
+        tagDao.deleteTag(objectId, ObjectType.ACCOUNT, tagDefinition.getId(), context);
         final Map<String, Tag> tagMapAfterDeletion = tagDao.loadEntities(objectId, ObjectType.ACCOUNT);
         assertEquals(tagMapAfterDeletion.size(), 0);
 
         try {
-            tagDefinitionDao.deleteTagDefinition(definitionName, context);
+            tagDefinitionDao.deleteById(tagDefinition.getId(), context);
         } catch (TagDefinitionApiException e) {
             fail("Could not delete tag definition", e);
         }
@@ -303,7 +311,7 @@ public class TestTagStore extends UtilTestSuiteWithEmbeddedDB {
         final UUID accountId = UUID.randomUUID();
 
         final TagStore tagStore = new DefaultTagStore(accountId, ObjectType.ACCOUNT);
-        final Tag tag = new DescriptiveTag(testTag);
+        final Tag tag = new DescriptiveTag(testTag.getId());
         tagStore.add(tag);
 
         tagDao.saveEntities(accountId, ObjectType.ACCOUNT, tagStore.getEntityList(), context);
@@ -311,8 +319,8 @@ public class TestTagStore extends UtilTestSuiteWithEmbeddedDB {
         final Map<String, Tag> savedTags = tagDao.loadEntities(accountId, ObjectType.ACCOUNT);
         assertEquals(savedTags.size(), 1);
 
-        final Tag savedTag = savedTags.get(tag.getTagDefinitionName());
-        assertEquals(savedTag.getTagDefinitionName(), tag.getTagDefinitionName());
+        final Tag savedTag = savedTags.get(tag.getId().toString());
+        assertEquals(savedTag.getTagDefinitionId(), tag.getTagDefinitionId());
         assertEquals(savedTag.getId(), tag.getId());
 
         final Handle handle = dbi.open();
@@ -335,7 +343,7 @@ public class TestTagStore extends UtilTestSuiteWithEmbeddedDB {
         final UUID accountId = UUID.randomUUID();
 
         final TagStore tagStore = new DefaultTagStore(accountId, ObjectType.ACCOUNT);
-        final Tag tag = new DescriptiveTag(testTag);
+        final Tag tag = new DescriptiveTag(testTag.getId());
         tagStore.add(tag);
 
         tagDao.saveEntities(accountId, ObjectType.ACCOUNT, tagStore.getEntityList(), context);
@@ -361,25 +369,25 @@ public class TestTagStore extends UtilTestSuiteWithEmbeddedDB {
     }
 
     @Test
-    public void testAddTag() throws TagApiException {
+    public void testAddTag() throws TagApiException, TagDefinitionApiException {
         final UUID objectId = UUID.randomUUID();
         final ObjectType objectType = ObjectType.INVOICE;
-        final TagDefinition tagDefinition = new DefaultTagDefinition("test tag", "test", false);
-        tagDao.insertTag(objectId, objectType, tagDefinition, context);
+        final TagDefinition tagDefinition = tagDefinitionDao.create("test tag", "test", context);
+        tagDao.insertTag(objectId, objectType, tagDefinition.getId(), context);
         final Map<String, Tag> savedTags = tagDao.loadEntities(objectId, objectType);
         assertEquals(savedTags.size(), 1);
     }
 
     @Test
-    public void testRemoveTag() throws TagApiException {
+    public void testRemoveTag() throws TagApiException, TagDefinitionApiException  {
         final UUID objectId = UUID.randomUUID();
         final ObjectType objectType = ObjectType.INVOICE;
-        final TagDefinition tagDefinition = new DefaultTagDefinition("test tag", "test", false);
-        tagDao.insertTag(objectId, objectType, tagDefinition, context);
+        final TagDefinition tagDefinition = tagDefinitionDao.create("test tag", "test", context);
+        tagDao.insertTag(objectId, objectType, tagDefinition.getId(), context);
         Map<String, Tag> savedTags = tagDao.loadEntities(objectId, objectType);
         assertEquals(savedTags.size(), 1);
 
-        tagDao.deleteTag(objectId, objectType, tagDefinition, context);
+        tagDao.deleteTag(objectId, objectType, tagDefinition.getId(), context);
         savedTags = tagDao.loadEntities(objectId, objectType);
         assertEquals(savedTags.size(), 0);
     }
@@ -390,8 +398,8 @@ public class TestTagStore extends UtilTestSuiteWithEmbeddedDB {
         final ObjectType objectType = ObjectType.INVOICE;
 
         final List<Tag> tags = new ArrayList<Tag>();
-        tags.add(new DescriptiveTag("test 1"));
-        tags.add(new DescriptiveTag("test 2"));
+        tags.add(new DescriptiveTag(UUID.randomUUID()));
+        tags.add(new DescriptiveTag(UUID.randomUUID()));
         tags.add(new DefaultControlTag(ControlTagType.AUTO_INVOICING_OFF));
         tagDao.saveEntities(objectId, objectType, tags, context);