killbill-aplcache

Changes

account/pom.xml 7(+1 -6)

api/pom.xml 6(+3 -3)

beatrix/pom.xml 2(+1 -1)

catalog/pom.xml 14(+13 -1)

entitlement/pom.xml 14(+1 -13)

invoice/pom.xml 25(+15 -10)

jaxrs/pom.xml 17(+2 -15)

junction/pom.xml 2(+1 -1)

overdue/pom.xml 2(+1 -1)

payment/pom.xml 2(+1 -1)

pom.xml 37(+21 -16)

server/pom.xml 5(+2 -3)

util/pom.xml 18(+9 -9)

Details

account/pom.xml 7(+1 -6)

diff --git a/account/pom.xml b/account/pom.xml
index 86cb9f7..c968f25 100644
--- a/account/pom.xml
+++ b/account/pom.xml
@@ -13,7 +13,7 @@
     <parent>
         <groupId>com.ning.billing</groupId>
         <artifactId>killbill</artifactId>
-        <version>0.1.12-SNAPSHOT</version>
+        <version>0.1.13-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <artifactId>killbill-account</artifactId>
@@ -88,11 +88,6 @@
             <artifactId>commons-io</artifactId>
             <scope>test</scope>
         </dependency>
-        <dependency>
-            <groupId>org.codehaus.jackson</groupId>
-            <artifactId>jackson-mapper-asl</artifactId>
-            <version>1.9.0</version>
-        </dependency>
     </dependencies>
     <build>
         <plugins>
diff --git a/account/src/main/java/com/ning/billing/account/api/DefaultChangedField.java b/account/src/main/java/com/ning/billing/account/api/DefaultChangedField.java
index c979fc6..89a65f6 100644
--- a/account/src/main/java/com/ning/billing/account/api/DefaultChangedField.java
+++ b/account/src/main/java/com/ning/billing/account/api/DefaultChangedField.java
@@ -16,9 +16,8 @@
 
 package com.ning.billing.account.api;
 
-
-import org.codehaus.jackson.annotate.JsonCreator;
-import org.codehaus.jackson.annotate.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
 import org.joda.time.DateTime;
 
 public class DefaultChangedField implements ChangedField {
diff --git a/account/src/main/java/com/ning/billing/account/api/user/DefaultAccountChangeEvent.java b/account/src/main/java/com/ning/billing/account/api/user/DefaultAccountChangeEvent.java
index 7b4c0d7..84f5995 100644
--- a/account/src/main/java/com/ning/billing/account/api/user/DefaultAccountChangeEvent.java
+++ b/account/src/main/java/com/ning/billing/account/api/user/DefaultAccountChangeEvent.java
@@ -16,6 +16,10 @@
 
 package com.ning.billing.account.api.user;
 
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
 import com.ning.billing.account.api.Account;
 import com.ning.billing.account.api.AccountChangeEvent;
 import com.ning.billing.account.api.ChangedField;
@@ -25,11 +29,6 @@ import java.util.ArrayList;
 import java.util.List;
 import java.util.UUID;
 
-import org.codehaus.jackson.annotate.JsonCreator;
-import org.codehaus.jackson.annotate.JsonIgnore;
-import org.codehaus.jackson.annotate.JsonProperty;
-import org.codehaus.jackson.map.annotate.JsonDeserialize;
-
 public class DefaultAccountChangeEvent implements AccountChangeEvent {
 	
 	private final UUID userToken;
diff --git a/account/src/main/java/com/ning/billing/account/api/user/DefaultAccountCreationEvent.java b/account/src/main/java/com/ning/billing/account/api/user/DefaultAccountCreationEvent.java
index 5dabd40..1c20f44 100644
--- a/account/src/main/java/com/ning/billing/account/api/user/DefaultAccountCreationEvent.java
+++ b/account/src/main/java/com/ning/billing/account/api/user/DefaultAccountCreationEvent.java
@@ -16,17 +16,16 @@
 
 package com.ning.billing.account.api.user;
 
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
 import com.ning.billing.account.api.Account;
 import com.ning.billing.account.api.AccountCreationEvent;
 import com.ning.billing.account.api.AccountData;
-import com.ning.billing.account.api.DefaultAccount;
 import com.ning.billing.catalog.api.Currency;
 
 import java.util.UUID;
 
-import org.codehaus.jackson.annotate.JsonCreator;
-import org.codehaus.jackson.annotate.JsonIgnore;
-import org.codehaus.jackson.annotate.JsonProperty;
 import org.joda.time.DateTimeZone;
 
 public class DefaultAccountCreationEvent implements AccountCreationEvent {
diff --git a/account/src/test/java/com/ning/billing/account/api/user/TestEventJson.java b/account/src/test/java/com/ning/billing/account/api/user/TestEventJson.java
index 6518355..7cfe1ba 100644
--- a/account/src/test/java/com/ning/billing/account/api/user/TestEventJson.java
+++ b/account/src/test/java/com/ning/billing/account/api/user/TestEventJson.java
@@ -19,10 +19,8 @@ import java.util.ArrayList;
 import java.util.List;
 import java.util.UUID;
 
-import org.codehaus.jackson.map.ObjectMapper;
-import org.codehaus.jackson.map.SerializationConfig;
+import com.ning.billing.util.jackson.ObjectMapper;
 import org.testng.Assert;
-import org.testng.annotations.BeforeTest;
 import org.testng.annotations.Test;
 
 import com.ning.billing.account.api.AccountChangeEvent;
@@ -31,14 +29,7 @@ import com.ning.billing.account.api.DefaultChangedField;
 import com.ning.billing.account.api.user.DefaultAccountCreationEvent.DefaultAccountData;
 
 public class TestEventJson {
-    
-    private ObjectMapper mapper = new ObjectMapper();
-    
-    @BeforeTest(groups= {"fast"})
-    public void setup() {
-        mapper = new ObjectMapper();
-        mapper.disable(SerializationConfig.Feature.WRITE_DATES_AS_TIMESTAMPS);
-    }
+    private final ObjectMapper mapper = new ObjectMapper();
 
     @Test(groups= {"fast"})
     public void testDefaultAccountChangeEvent() throws Exception {
diff --git a/analytics/pom.xml b/analytics/pom.xml
index d368d32..6015994 100644
--- a/analytics/pom.xml
+++ b/analytics/pom.xml
@@ -13,7 +13,7 @@
     <parent>
         <groupId>com.ning.billing</groupId>
         <artifactId>killbill</artifactId>
-        <version>0.1.12-SNAPSHOT</version>
+        <version>0.1.13-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <artifactId>killbill-analytics</artifactId>
@@ -31,6 +31,10 @@
             <scope>provided</scope>
         </dependency>
         <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-log4j12</artifactId>
+        </dependency>
+        <dependency>
             <groupId>com.ning.billing</groupId>
             <artifactId>killbill-api</artifactId>
         </dependency>
diff --git a/analytics/src/test/java/com/ning/billing/analytics/api/TestAnalyticsService.java b/analytics/src/test/java/com/ning/billing/analytics/api/TestAnalyticsService.java
index 43e046f..3a8637f 100644
--- a/analytics/src/test/java/com/ning/billing/analytics/api/TestAnalyticsService.java
+++ b/analytics/src/test/java/com/ning/billing/analytics/api/TestAnalyticsService.java
@@ -280,8 +280,7 @@ public class TestAnalyticsService {
         invoiceCreationNotification = new DefaultInvoiceCreationEvent(invoice.getId(), account.getId(),
                 INVOICE_AMOUNT, ACCOUNT_CURRENCY, clock.getUTCNow(), null);
 
-
-        paymentInfoNotification = new DefaultPaymentInfoEvent.Builder().setId(UUID.randomUUID()).setPaymentMethod(PAYMENT_METHOD).setCardCountry(CARD_COUNTRY).build();
+        paymentInfoNotification = new DefaultPaymentInfoEvent.Builder().setId(UUID.randomUUID()).setExternalPaymentId("12345abcdef").setPaymentMethod(PAYMENT_METHOD).setCardCountry(CARD_COUNTRY).build();
         final PaymentAttempt paymentAttempt = new DefaultPaymentAttempt(UUID.randomUUID(), invoice.getId(), account.getId(), BigDecimal.TEN,
                 ACCOUNT_CURRENCY, clock.getUTCNow(), clock.getUTCNow(), paymentInfoNotification.getId(), 1, new DateTime(), new DateTime(), PaymentAttemptStatus.COMPLETED_SUCCESS);
         paymentDao.createPaymentAttempt(paymentAttempt, PaymentAttemptStatus.COMPLETED_SUCCESS, context);

api/pom.xml 6(+3 -3)

diff --git a/api/pom.xml b/api/pom.xml
index 5b8380c..cd76c4d 100644
--- a/api/pom.xml
+++ b/api/pom.xml
@@ -13,7 +13,7 @@
     <parent>
         <groupId>com.ning.billing</groupId>
         <artifactId>killbill</artifactId>
-        <version>0.1.12-SNAPSHOT</version>
+        <version>0.1.13-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <artifactId>killbill-api</artifactId>
@@ -51,8 +51,8 @@
             <artifactId>config-magic</artifactId>
         </dependency>
         <dependency>
-            <groupId>org.codehaus.jackson</groupId>
-            <artifactId>jackson-core-asl</artifactId>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-annotations</artifactId>
         </dependency>
         <dependency>
             <groupId>commons-lang</groupId>
diff --git a/api/src/main/java/com/ning/billing/payment/api/CreditCardPaymentMethodInfo.java b/api/src/main/java/com/ning/billing/payment/api/CreditCardPaymentMethodInfo.java
index bc3d372..dcffe18 100644
--- a/api/src/main/java/com/ning/billing/payment/api/CreditCardPaymentMethodInfo.java
+++ b/api/src/main/java/com/ning/billing/payment/api/CreditCardPaymentMethodInfo.java
@@ -16,9 +16,8 @@
 
 package com.ning.billing.payment.api;
 
-import org.codehaus.jackson.annotate.JsonCreator;
-import org.codehaus.jackson.annotate.JsonProperty;
-
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
 
 public final class CreditCardPaymentMethodInfo extends PaymentMethodInfo {
     private final String cardHolderName;
diff --git a/api/src/main/java/com/ning/billing/payment/api/Either.java b/api/src/main/java/com/ning/billing/payment/api/Either.java
new file mode 100644
index 0000000..a4ae71f
--- /dev/null
+++ b/api/src/main/java/com/ning/billing/payment/api/Either.java
@@ -0,0 +1,85 @@
+/*
+ * 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.payment.api;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonValue;
+
+public abstract class Either<T, V> {
+    public static <T, V> Either<T, V> left(T value) {
+        return new Left<T, V>(value);
+    }
+    public static <T, V> Either<T, V> right(V value) {
+        return new Right<T, V>(value);
+    }
+
+    private Either() {
+    }
+
+    @JsonIgnore
+    public boolean isLeft() {
+        return false;
+    }
+
+    @JsonIgnore
+    public boolean isRight() {
+        return false;
+    }
+    public T getLeft() {
+        throw new UnsupportedOperationException();
+    }
+    public V getRight() {
+        throw new UnsupportedOperationException();
+    }
+
+    public static class Left<T, V> extends Either<T, V> {
+        private final T value;
+
+        public Left(T value) {
+            this.value = value;
+        }
+        @Override
+        @JsonIgnore
+        public boolean isLeft() {
+            return true;
+        }
+        @Override
+        @JsonValue
+        public T getLeft() {
+            return value;
+        }
+    }
+
+    public static class Right<T, V> extends Either<T, V> {
+        private final V value;
+
+        public Right(V value) {
+            this.value = value;
+        }
+        @Override
+        @JsonIgnore
+        public boolean isRight() {
+            return true;
+        }
+
+        @Override
+        @JsonValue
+        public V getRight() {
+            return value;
+        }
+    }
+}
diff --git a/api/src/main/java/com/ning/billing/payment/api/PaymentInfoEvent.java b/api/src/main/java/com/ning/billing/payment/api/PaymentInfoEvent.java
index c9b1a57..bbfe3c3 100644
--- a/api/src/main/java/com/ning/billing/payment/api/PaymentInfoEvent.java
+++ b/api/src/main/java/com/ning/billing/payment/api/PaymentInfoEvent.java
@@ -21,9 +21,9 @@ import com.ning.billing.util.entity.Entity;
 import org.joda.time.DateTime;
 import com.ning.billing.util.bus.BusEvent;
 
-
 public interface PaymentInfoEvent extends Entity, BusEvent {
-
+    public String getExternalPaymentId();
+    
     public UUID getAccountId();
     
     public UUID getInvoiceId();
diff --git a/api/src/main/java/com/ning/billing/payment/api/PaypalPaymentMethodInfo.java b/api/src/main/java/com/ning/billing/payment/api/PaypalPaymentMethodInfo.java
index 3b2ebed..18f61d2 100644
--- a/api/src/main/java/com/ning/billing/payment/api/PaypalPaymentMethodInfo.java
+++ b/api/src/main/java/com/ning/billing/payment/api/PaypalPaymentMethodInfo.java
@@ -16,12 +16,10 @@
 
 package com.ning.billing.payment.api;
 
-import org.codehaus.jackson.annotate.JsonCreator;
-import org.codehaus.jackson.annotate.JsonProperty;
-
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
 import com.google.common.base.Strings;
 
-
 public final class PaypalPaymentMethodInfo extends PaymentMethodInfo {
     public static final String TYPE = "PayPal";
 
diff --git a/api/src/main/java/com/ning/billing/payment/plugin/api/PaymentInfoPlugin.java b/api/src/main/java/com/ning/billing/payment/plugin/api/PaymentInfoPlugin.java
index 8f1117b..e338e69 100644
--- a/api/src/main/java/com/ning/billing/payment/plugin/api/PaymentInfoPlugin.java
+++ b/api/src/main/java/com/ning/billing/payment/plugin/api/PaymentInfoPlugin.java
@@ -21,6 +21,7 @@ import java.util.UUID;
 import org.joda.time.DateTime;
 
 public interface PaymentInfoPlugin {
+    public String getExternalPaymentId();
     
     public BigDecimal getAmount();
 
diff --git a/api/src/main/java/com/ning/billing/util/dao/ObjectType.java b/api/src/main/java/com/ning/billing/util/dao/ObjectType.java
index 18d987c..196cc19 100644
--- a/api/src/main/java/com/ning/billing/util/dao/ObjectType.java
+++ b/api/src/main/java/com/ning/billing/util/dao/ObjectType.java
@@ -21,6 +21,7 @@ public enum ObjectType {
     ACCOUNT_EMAIL("account email"),
     BUNDLE("subscription bundle"),
     INVOICE("invoice"),
+    PAYMENT("payment"),
     RECURRING_INVOICE_ITEM("recurring_invoice_item"),
     SUBSCRIPTION("subscription");
 

beatrix/pom.xml 2(+1 -1)

diff --git a/beatrix/pom.xml b/beatrix/pom.xml
index 31db273..a81c264 100644
--- a/beatrix/pom.xml
+++ b/beatrix/pom.xml
@@ -13,7 +13,7 @@
     <parent>
         <groupId>com.ning.billing</groupId>
         <artifactId>killbill</artifactId>
-        <version>0.1.12-SNAPSHOT</version>
+        <version>0.1.13-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <artifactId>killbill-beatrix</artifactId>

catalog/pom.xml 14(+13 -1)

diff --git a/catalog/pom.xml b/catalog/pom.xml
index e6d767f..3ad08f6 100644
--- a/catalog/pom.xml
+++ b/catalog/pom.xml
@@ -13,7 +13,7 @@
     <parent>
         <groupId>com.ning.billing</groupId>
         <artifactId>killbill</artifactId>
-        <version>0.1.12-SNAPSHOT</version>
+        <version>0.1.13-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <artifactId>killbill-catalog</artifactId>
@@ -48,6 +48,18 @@
             <artifactId>guice</artifactId>
             <scope>provided</scope>
         </dependency>
+        <dependency>
+            <groupId>joda-time</groupId>
+            <artifactId>joda-time</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-log4j12</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.skife.config</groupId>
+            <artifactId>config-magic</artifactId>
+        </dependency>
     </dependencies>
      <build>
         <plugins>

entitlement/pom.xml 14(+1 -13)

diff --git a/entitlement/pom.xml b/entitlement/pom.xml
index 808876b..1eddb80 100644
--- a/entitlement/pom.xml
+++ b/entitlement/pom.xml
@@ -13,7 +13,7 @@
     <parent>
         <groupId>com.ning.billing</groupId>
         <artifactId>killbill</artifactId>
-        <version>0.1.12-SNAPSHOT</version>
+        <version>0.1.13-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <artifactId>killbill-entitlement</artifactId>
@@ -63,18 +63,6 @@
             <artifactId>slf4j-log4j12</artifactId>
         </dependency>
         <dependency>
-            <groupId>org.codehaus.jackson</groupId>
-            <artifactId>jackson-core-asl</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.codehaus.jackson</groupId>
-            <artifactId>jackson-jaxrs</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.codehaus.jackson</groupId>
-            <artifactId>jackson-mapper-asl</artifactId>
-        </dependency>
-        <dependency>
             <groupId>org.antlr</groupId>
             <artifactId>stringtemplate</artifactId>
             <scope>runtime</scope>
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/api/timeline/DefaultRepairEntitlementEvent.java b/entitlement/src/main/java/com/ning/billing/entitlement/api/timeline/DefaultRepairEntitlementEvent.java
index 938f99f..b1cc31c 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/api/timeline/DefaultRepairEntitlementEvent.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/api/timeline/DefaultRepairEntitlementEvent.java
@@ -17,13 +17,11 @@ package com.ning.billing.entitlement.api.timeline;
 
 import java.util.UUID;
 
-import org.codehaus.jackson.annotate.JsonCreator;
-import org.codehaus.jackson.annotate.JsonIgnore;
-import org.codehaus.jackson.annotate.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
 import org.joda.time.DateTime;
 
-import com.ning.billing.entitlement.api.timeline.RepairEntitlementEvent;
-
 public class DefaultRepairEntitlementEvent implements RepairEntitlementEvent {
 
     private final UUID userToken;
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/DefaultSubscriptionEvent.java b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/DefaultSubscriptionEvent.java
index 3cf74ec..333cc4e 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/DefaultSubscriptionEvent.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/DefaultSubscriptionEvent.java
@@ -17,9 +17,9 @@ package com.ning.billing.entitlement.api.user;
 
 import java.util.UUID;
 
-import org.codehaus.jackson.annotate.JsonCreator;
-import org.codehaus.jackson.annotate.JsonIgnore;
-import org.codehaus.jackson.annotate.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
 import org.joda.time.DateTime;
 
 import com.ning.billing.entitlement.api.SubscriptionTransitionType;
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionTransitionData.java b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionTransitionData.java
index d5885d5..4a8d90b 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionTransitionData.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionTransitionData.java
@@ -18,8 +18,6 @@ package com.ning.billing.entitlement.api.user;
 
 import java.util.UUID;
 
-import org.codehaus.jackson.annotate.JsonIgnore;
-import org.codehaus.jackson.annotate.JsonProperty;
 import org.joda.time.DateTime;
 
 import com.ning.billing.catalog.api.Plan;
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/AuditedEntitlementDao.java b/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/AuditedEntitlementDao.java
index 656a128..b6a2f01 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/AuditedEntitlementDao.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/AuditedEntitlementDao.java
@@ -216,7 +216,7 @@ public class AuditedEntitlementDao implements EntitlementDao {
                 transactional.insertEvent(nextPhase, context);
 
                 Long recordId = transactional.getRecordId(nextPhase.getId().toString());
-                EntityAudit audit = new EntityAudit(TableName.ENTITLEMENT_EVENTS, recordId, ChangeType.INSERT);
+                EntityAudit audit = new EntityAudit(TableName.SUBSCRIPTION_EVENTS, recordId, ChangeType.INSERT);
                 transactional.insertAuditFromTransaction(audit, context);
 
                 recordFutureNotificationFromTransaction(transactional,
@@ -286,7 +286,7 @@ public class AuditedEntitlementDao implements EntitlementDao {
                 for (final EntitlementEvent cur : initialEvents) {
                     eventsDaoFromSameTransaction.insertEvent(cur, context);
                     Long recordId = eventsDaoFromSameTransaction.getRecordId(cur.getId().toString());
-                    audits.add(new EntityAudit(TableName.ENTITLEMENT_EVENTS, recordId, ChangeType.INSERT));
+                    audits.add(new EntityAudit(TableName.SUBSCRIPTION_EVENTS, recordId, ChangeType.INSERT));
                     recordFutureNotificationFromTransaction(transactional,
                             cur.getEffectiveDate(),
                             new EntitlementNotificationKey(cur.getId()));
@@ -311,7 +311,7 @@ public class AuditedEntitlementDao implements EntitlementDao {
                 for (final EntitlementEvent cur : recreateEvents) {
                     transactional.insertEvent(cur, context);
                     Long recordId = transactional.getRecordId(cur.getId().toString());
-                    audits.add(new EntityAudit(TableName.ENTITLEMENT_EVENTS, recordId, ChangeType.INSERT));
+                    audits.add(new EntityAudit(TableName.SUBSCRIPTION_EVENTS, recordId, ChangeType.INSERT));
                     recordFutureNotificationFromTransaction(transactional,
                             cur.getEffectiveDate(),
                             new EntitlementNotificationKey(cur.getId()));
@@ -338,7 +338,7 @@ public class AuditedEntitlementDao implements EntitlementDao {
                 String cancelEventId = cancelEvent.getId().toString();
 
                 Long recordId = transactional.getRecordId(cancelEventId);
-                EntityAudit audit = new EntityAudit(TableName.ENTITLEMENT_EVENTS, recordId, ChangeType.INSERT);
+                EntityAudit audit = new EntityAudit(TableName.SUBSCRIPTION_EVENTS, recordId, ChangeType.INSERT);
                 transactional.insertAuditFromTransaction(audit, context);
 
                 recordFutureNotificationFromTransaction(transactional,
@@ -377,12 +377,12 @@ public class AuditedEntitlementDao implements EntitlementDao {
                     String cancelledEventId = cancelledEvent.getId().toString();
                     transactional.unactiveEvent(cancelledEventId, context);
                     Long cancelledRecordId = transactional.getRecordId(cancelledEventId);
-                    eventAudits.add(new EntityAudit(TableName.ENTITLEMENT_EVENTS, cancelledRecordId, ChangeType.UPDATE));
+                    eventAudits.add(new EntityAudit(TableName.SUBSCRIPTION_EVENTS, cancelledRecordId, ChangeType.UPDATE));
 
                     for (final EntitlementEvent cur : uncancelEvents) {
                         transactional.insertEvent(cur, context);
                         Long recordId = transactional.getRecordId(cur.getId().toString());
-                        eventAudits.add(new EntityAudit(TableName.ENTITLEMENT_EVENTS, recordId, ChangeType.INSERT));
+                        eventAudits.add(new EntityAudit(TableName.SUBSCRIPTION_EVENTS, recordId, ChangeType.INSERT));
                         recordFutureNotificationFromTransaction(transactional,
                                 cur.getEffectiveDate(),
                                 new EntitlementNotificationKey(cur.getId()));
@@ -407,7 +407,7 @@ public class AuditedEntitlementDao implements EntitlementDao {
                 for (final EntitlementEvent cur : changeEvents) {
                     transactional.insertEvent(cur, context);
                     Long recordId = transactional.getRecordId(cur.getId().toString());
-                    eventAudits.add(new EntityAudit(TableName.ENTITLEMENT_EVENTS, recordId, ChangeType.INSERT));
+                    eventAudits.add(new EntityAudit(TableName.SUBSCRIPTION_EVENTS, recordId, ChangeType.INSERT));
 
                     recordFutureNotificationFromTransaction(transactional,
                             cur.getEffectiveDate(),
@@ -455,7 +455,7 @@ public class AuditedEntitlementDao implements EntitlementDao {
             String eventId = futureEvent.getId().toString();
             dao.unactiveEvent(eventId, context);
             Long recordId = dao.getRecordId(eventId);
-            EntityAudit audit = new EntityAudit(TableName.ENTITLEMENT_EVENTS, recordId, ChangeType.UPDATE);
+            EntityAudit audit = new EntityAudit(TableName.SUBSCRIPTION_EVENTS, recordId, ChangeType.UPDATE);
             dao.insertAuditFromTransaction(audit, context);
         }
     }
@@ -576,7 +576,7 @@ public class AuditedEntitlementDao implements EntitlementDao {
                         for (final EntitlementEvent curEvent : curSubscription.getInitialEvents()) {
                             transactional.insertEvent(curEvent, context);
                             recordId = transactional.getRecordId(curEvent.getId().toString());
-                            audits.add(new EntityAudit(TableName.ENTITLEMENT_EVENTS, recordId, ChangeType.INSERT));
+                            audits.add(new EntityAudit(TableName.SUBSCRIPTION_EVENTS, recordId, ChangeType.INSERT));
 
                             recordFutureNotificationFromTransaction(transactional,
                                     curEvent.getEffectiveDate(),
diff --git a/entitlement/src/main/resources/com/ning/billing/entitlement/ddl.sql b/entitlement/src/main/resources/com/ning/billing/entitlement/ddl.sql
index f86f170..f69a20d 100644
--- a/entitlement/src/main/resources/com/ning/billing/entitlement/ddl.sql
+++ b/entitlement/src/main/resources/com/ning/billing/entitlement/ddl.sql
@@ -1,6 +1,7 @@
 DROP TABLE IF EXISTS events;
 DROP TABLE IF EXISTS entitlement_events;
-CREATE TABLE entitlement_events (
+DROP TABLE IF EXISTS subscription_events;
+CREATE TABLE subscription_events (
     record_id int(11) unsigned NOT NULL AUTO_INCREMENT,
     id char(36) NOT NULL,
     event_type varchar(9) NOT NULL,
@@ -20,9 +21,9 @@ CREATE TABLE entitlement_events (
     updated_date datetime NOT NULL,
     PRIMARY KEY(record_id)
 ) ENGINE=innodb;
-CREATE UNIQUE INDEX entitlement_events_id ON entitlement_events(id);
-CREATE INDEX idx_ent_1 ON entitlement_events(subscription_id,is_active,effective_date);
-CREATE INDEX idx_ent_2 ON entitlement_events(subscription_id,effective_date,created_date,requested_date,id);
+CREATE UNIQUE INDEX subscription_events_id ON subscription_events(id);
+CREATE INDEX idx_ent_1 ON subscription_events(subscription_id, is_active, effective_date);
+CREATE INDEX idx_ent_2 ON subscription_events(subscription_id, effective_date, created_date, requested_date,id);
 
 DROP TABLE IF EXISTS subscriptions;
 CREATE TABLE subscriptions (
diff --git a/entitlement/src/main/resources/com/ning/billing/entitlement/engine/dao/EntitlementEventSqlDao.sql.stg b/entitlement/src/main/resources/com/ning/billing/entitlement/engine/dao/EntitlementEventSqlDao.sql.stg
index f4472f9..09bf42d 100644
--- a/entitlement/src/main/resources/com/ning/billing/entitlement/engine/dao/EntitlementEventSqlDao.sql.stg
+++ b/entitlement/src/main/resources/com/ning/billing/entitlement/engine/dao/EntitlementEventSqlDao.sql.stg
@@ -21,14 +21,14 @@ fields(prefix) ::= <<
 
 getEventById() ::= <<
   select record_id, <fields()>
-  from entitlement_events
+  from subscription_events
   where
       id = :id
   ;
 >>
 
 insertEvent() ::= <<
-    insert into entitlement_events (<fields()>)
+    insert into subscription_events (<fields()>)
     values (
     :id
     , :eventType
@@ -50,7 +50,7 @@ insertEvent() ::= <<
 >>
 
 updateVersion() ::= <<
-    update entitlement_events
+    update subscription_events
     set
       current_version = :currentVersion
     where
@@ -59,7 +59,7 @@ updateVersion() ::= <<
 >>
 
 unactiveEvent() ::= <<
-    update entitlement_events
+    update subscription_events
     set
       is_active = 0
       , updated_by = :userName
@@ -70,7 +70,7 @@ unactiveEvent() ::= <<
 >>
 
 reactiveEvent() ::= <<
-    update entitlement_events
+    update subscription_events
     set
       is_active = 1
       , updated_by = :userName
@@ -83,7 +83,7 @@ reactiveEvent() ::= <<
 
 getFutureActiveEventForSubscription() ::= <<
     select record_id, <fields()>
-    from entitlement_events
+    from subscription_events
     where
       subscription_id = :subscriptionId
       and is_active = 1
@@ -98,7 +98,7 @@ getFutureActiveEventForSubscription() ::= <<
 
 getEventsForSubscription() ::= <<
     select record_id, <fields()>
-    from entitlement_events
+    from subscription_events
     where
       subscription_id = :subscriptionId
     order by
@@ -111,7 +111,7 @@ getEventsForSubscription() ::= <<
 
 getRecordId() ::= <<
     SELECT record_id
-    FROM entitlement_events
+    FROM subscription_events
     WHERE id = :id;
 >>
 
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/TestEventJson.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/TestEventJson.java
index 49e9ed7..e50fd41 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/TestEventJson.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/TestEventJson.java
@@ -17,11 +17,9 @@ package com.ning.billing.entitlement.api;
 
 import java.util.UUID;
 
-import org.codehaus.jackson.map.ObjectMapper;
-import org.codehaus.jackson.map.SerializationConfig;
+import com.ning.billing.util.jackson.ObjectMapper;
 import org.joda.time.DateTime;
 import org.testng.Assert;
-import org.testng.annotations.BeforeTest;
 import org.testng.annotations.Test;
 
 import com.ning.billing.entitlement.api.timeline.DefaultRepairEntitlementEvent;
@@ -31,15 +29,7 @@ import com.ning.billing.entitlement.api.user.Subscription.SubscriptionState;
 import com.ning.billing.entitlement.api.user.SubscriptionEvent;
 
 public class TestEventJson {
-
-
-    private ObjectMapper mapper = new ObjectMapper();
-
-    @BeforeTest(groups= {"fast"})
-    public void setup() {
-        mapper = new ObjectMapper();
-        mapper.disable(SerializationConfig.Feature.WRITE_DATES_AS_TIMESTAMPS);
-    }
+    private final ObjectMapper mapper = new ObjectMapper();
 
     @Test(groups= {"fast"})
     public void testSubscriptionEvent() throws Exception {
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/engine/dao/MockEntitlementDaoSql.java b/entitlement/src/test/java/com/ning/billing/entitlement/engine/dao/MockEntitlementDaoSql.java
index c197434..71f3168 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/engine/dao/MockEntitlementDaoSql.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/engine/dao/MockEntitlementDaoSql.java
@@ -61,7 +61,7 @@ public class MockEntitlementDaoSql extends AuditedEntitlementDao implements Mock
 
     public static interface ResetSqlDao extends Transactional<ResetSqlDao>, CloseMe {
 
-        @SqlUpdate("truncate table entitlement_events")
+        @SqlUpdate("truncate table subscription_events")
         public void resetEvents();
 
         @SqlUpdate("truncate table subscriptions")

invoice/pom.xml 25(+15 -10)

diff --git a/invoice/pom.xml b/invoice/pom.xml
index 6b5a555..3767525 100644
--- a/invoice/pom.xml
+++ b/invoice/pom.xml
@@ -13,7 +13,7 @@
     <parent>
         <groupId>com.ning.billing</groupId>
         <artifactId>killbill</artifactId>
-        <version>0.1.12-SNAPSHOT</version>
+        <version>0.1.13-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <artifactId>killbill-invoice</artifactId>
@@ -48,19 +48,24 @@
             <scope>provided</scope>
         </dependency>
         <dependency>
-            <groupId>org.codehaus.jackson</groupId>
-            <artifactId>jackson-core-asl</artifactId>
-            <version>1.9.5</version>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-core</artifactId>
         </dependency>
         <dependency>
-            <groupId>org.codehaus.jackson</groupId>
-            <artifactId>jackson-jaxrs</artifactId>
-            <version>1.9.5</version>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-annotations</artifactId>
         </dependency>
         <dependency>
-            <groupId>org.codehaus.jackson</groupId>
-            <artifactId>jackson-mapper-asl</artifactId>
-            <version>1.9.5</version>
+            <groupId>joda-time</groupId>
+            <artifactId>joda-time</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-log4j12</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.skife.config</groupId>
+            <artifactId>config-magic</artifactId>
         </dependency>
        <!-- TEST SCOPE -->
         <dependency>
diff --git a/invoice/src/main/java/com/ning/billing/invoice/api/user/DefaultEmptyInvoiceEvent.java b/invoice/src/main/java/com/ning/billing/invoice/api/user/DefaultEmptyInvoiceEvent.java
index 6ce30f6..97b32ae 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/api/user/DefaultEmptyInvoiceEvent.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/api/user/DefaultEmptyInvoiceEvent.java
@@ -13,23 +13,22 @@
  * License for the specific language governing permissions and limitations
  * under the License.
  */
+
 package com.ning.billing.invoice.api.user;
 
 import java.util.UUID;
 
-import org.codehaus.jackson.annotate.JsonCreator;
-import org.codehaus.jackson.annotate.JsonIgnore;
-import org.codehaus.jackson.annotate.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
 import org.joda.time.DateTime;
 
 import com.ning.billing.invoice.api.EmptyInvoiceEvent;
 
 public class DefaultEmptyInvoiceEvent implements EmptyInvoiceEvent {
-
     private final UUID accountId;
     private final DateTime processingDate;
     private final UUID userToken;
-
     
     @JsonCreator
     public DefaultEmptyInvoiceEvent(@JsonProperty("accountId") final UUID accountId,
diff --git a/invoice/src/main/java/com/ning/billing/invoice/api/user/DefaultInvoiceCreationEvent.java b/invoice/src/main/java/com/ning/billing/invoice/api/user/DefaultInvoiceCreationEvent.java
index de89f16..7ba10fb 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/api/user/DefaultInvoiceCreationEvent.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/api/user/DefaultInvoiceCreationEvent.java
@@ -19,14 +19,13 @@ package com.ning.billing.invoice.api.user;
 import java.math.BigDecimal;
 import java.util.UUID;
 
-import org.codehaus.jackson.annotate.JsonCreator;
-import org.codehaus.jackson.annotate.JsonIgnore;
-import org.codehaus.jackson.annotate.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
 import org.joda.time.DateTime;
 
 import com.ning.billing.catalog.api.Currency;
 import com.ning.billing.invoice.api.InvoiceCreationEvent;
-import com.ning.billing.util.bus.BusEvent.BusEventType;
 
 public class DefaultInvoiceCreationEvent implements InvoiceCreationEvent {
 	
diff --git a/invoice/src/test/java/com/ning/billing/invoice/api/user/TestEventJson.java b/invoice/src/test/java/com/ning/billing/invoice/api/user/TestEventJson.java
index eb991dd..f2d9282 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/api/user/TestEventJson.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/api/user/TestEventJson.java
@@ -18,11 +18,9 @@ package com.ning.billing.invoice.api.user;
 import java.math.BigDecimal;
 import java.util.UUID;
 
-import org.codehaus.jackson.map.ObjectMapper;
-import org.codehaus.jackson.map.SerializationConfig;
+import com.ning.billing.util.jackson.ObjectMapper;
 import org.joda.time.DateTime;
 import org.testng.Assert;
-import org.testng.annotations.BeforeTest;
 import org.testng.annotations.Test;
 
 import com.ning.billing.catalog.api.Currency;
@@ -30,14 +28,7 @@ import com.ning.billing.invoice.api.EmptyInvoiceEvent;
 import com.ning.billing.invoice.api.InvoiceCreationEvent;
 
 public class TestEventJson {
-
-    private ObjectMapper mapper = new ObjectMapper();
-
-    @BeforeTest(groups= {"fast"})
-    public void setup() {
-        mapper = new ObjectMapper();
-        mapper.disable(SerializationConfig.Feature.WRITE_DATES_AS_TIMESTAMPS);
-    }
+    private final ObjectMapper mapper = new ObjectMapper();
 
     @Test(groups= {"fast"})
     public void testInvoiceCreationEvent() throws Exception {
diff --git a/invoice/src/test/java/com/ning/billing/invoice/tests/DefaultInvoiceGeneratorTests.java b/invoice/src/test/java/com/ning/billing/invoice/tests/DefaultInvoiceGeneratorTests.java
index 6c3dd65..75b57ec 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/tests/DefaultInvoiceGeneratorTests.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/tests/DefaultInvoiceGeneratorTests.java
@@ -19,6 +19,7 @@ package com.ning.billing.invoice.tests;
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertNotNull;
 import static org.testng.Assert.assertNull;
+import static org.testng.Assert.fail;
 
 import java.math.BigDecimal;
 import java.util.ArrayList;
@@ -710,7 +711,7 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
         assertEquals(invoice.getTotalAmount(), expectedAmount);
     }
 
-    @Test(groups = {"fast", "invoicing"})
+    @Test
     public void testAddOnInvoiceGeneration() throws CatalogApiException, InvoiceApiException {
         DateTime april25 = new DateTime(2012, 4, 25, 0, 0, 0, 0);
 
@@ -773,7 +774,7 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
         assertEquals(invoice3.getTotalAmount().compareTo(FIFTEEN.negate()), 0);
     }
 
-    @Test(enabled = false)
+    @Test
     public void testRepairForPaidInvoice() throws CatalogApiException, InvoiceApiException {
         // create an invoice
         DateTime april25 = new DateTime(2012, 4, 25, 0, 0, 0, 0);
@@ -821,5 +822,40 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
 
     }
 
-    // TODO: Jeff C -- how do we ensure that an annual add-on is properly aligned *at the end* with the base plan?
+    /*
+    test scenario: create invoice, pay invoice, change entitlement (repair)
+
+    test scenario: two subscriptions, one with auto_invoice_off
+
+    test scenario: create invoice, pay invoice, change entitlement, generate invoices to use up credits
+
+    test scenario: create invoice, pay invoice, add account-level credit, generate invoice
+
+
+     */
+
+    @Test
+    public void testAutoInvoiceOff() {
+        BillingEventSet eventSet = new BillingEventSet();
+        fail();
+    }
+
+    @Test(enabled = false)
+    public void testAccountCredit() throws CatalogApiException, InvoiceApiException {
+        BillingEventSet billingEventSet = new BillingEventSet();
+
+        DateTime startDate = new DateTime(2012, 3, 1, 0, 0, 0, 0);
+        UUID accountId = UUID.randomUUID();
+        UUID subscriptionId = UUID.randomUUID();
+        Plan plan = new MockPlan("original plan");
+        MockInternationalPrice price10 = new MockInternationalPrice(new DefaultPrice(TEN, Currency.USD));
+        PlanPhase planPhase = new MockPlanPhase(price10, null, BillingPeriod.MONTHLY, PhaseType.EVERGREEN);
+        BillingEvent creation = createBillingEvent(subscriptionId, startDate, plan, planPhase, 1);
+        billingEventSet.add(creation);
+
+        Invoice invoice = generator.generateInvoice(accountId, billingEventSet, null, startDate, Currency.USD);
+        assertNotNull(invoice);
+        assertEquals(invoice.getNumberOfItems(), 1);
+        assertEquals(invoice.getTotalAmount().compareTo(TEN), 0);
+    }
 }
\ No newline at end of file

jaxrs/pom.xml 17(+2 -15)

diff --git a/jaxrs/pom.xml b/jaxrs/pom.xml
index caa3692..c8fc0cd 100644
--- a/jaxrs/pom.xml
+++ b/jaxrs/pom.xml
@@ -8,13 +8,12 @@
     OR CONDITIONS OF ANY KIND, either express or implied. See the ~ License for 
     the specific language governing permissions and limitations ~ under the License. -->
 
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <modelVersion>4.0.0</modelVersion>
     <parent>
         <groupId>com.ning.billing</groupId>
         <artifactId>killbill</artifactId>
-        <version>0.1.12-SNAPSHOT</version>
+        <version>0.1.13-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <artifactId>killbill-jaxrs</artifactId>
@@ -62,18 +61,6 @@
             <artifactId>slf4j-log4j12</artifactId>
         </dependency>
         <dependency>
-            <groupId>org.codehaus.jackson</groupId>
-            <artifactId>jackson-core-asl</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.codehaus.jackson</groupId>
-            <artifactId>jackson-jaxrs</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.codehaus.jackson</groupId>
-            <artifactId>jackson-mapper-asl</artifactId>
-        </dependency>
-        <dependency>
             <groupId>org.testng</groupId>
             <artifactId>testng</artifactId>
             <scope>test</scope>
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/AccountJson.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/AccountJson.java
index 82645a5..7d3a663 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/AccountJson.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/AccountJson.java
@@ -16,9 +16,9 @@
 
 package com.ning.billing.jaxrs.json;
 
-import org.codehaus.jackson.annotate.JsonCreator;
-import org.codehaus.jackson.annotate.JsonProperty;
-import org.codehaus.jackson.map.annotate.JsonView;
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonView;
 import org.joda.time.DateTimeZone;
 
 import com.ning.billing.account.api.Account;
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/AccountJsonSimple.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/AccountJsonSimple.java
index d7e1b2d..eef25be 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/AccountJsonSimple.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/AccountJsonSimple.java
@@ -15,9 +15,9 @@
  */
 package com.ning.billing.jaxrs.json;
 
-import org.codehaus.jackson.annotate.JsonCreator;
-import org.codehaus.jackson.annotate.JsonProperty;
-import org.codehaus.jackson.map.annotate.JsonView;
+import com.fasterxml.jackson.annotation.JsonView;
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
 
 public class AccountJsonSimple {
 
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/AccountTimelineJson.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/AccountTimelineJson.java
index 881745a..c9f627a 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/AccountTimelineJson.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/AccountTimelineJson.java
@@ -22,9 +22,9 @@ import java.util.List;
 import java.util.Set;
 import java.util.UUID;
 
-import org.codehaus.jackson.annotate.JsonCreator;
-import org.codehaus.jackson.annotate.JsonProperty;
-import org.codehaus.jackson.map.annotate.JsonView;
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonView;
 
 import com.ning.billing.account.api.Account;
 import com.ning.billing.entitlement.api.timeline.BundleTimeline;
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/BundleJsonSimple.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/BundleJsonSimple.java
index 8c2d836..b20f435 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/BundleJsonSimple.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/BundleJsonSimple.java
@@ -15,9 +15,9 @@
  */
 package com.ning.billing.jaxrs.json;
 
-import org.codehaus.jackson.annotate.JsonCreator;
-import org.codehaus.jackson.annotate.JsonProperty;
-import org.codehaus.jackson.map.annotate.JsonView;
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonView;
 
 public class BundleJsonSimple {
     
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/BundleJsonWithSubscriptions.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/BundleJsonWithSubscriptions.java
index fa45cdd..10c90db 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/BundleJsonWithSubscriptions.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/BundleJsonWithSubscriptions.java
@@ -19,9 +19,9 @@ import java.util.LinkedList;
 import java.util.List;
 import java.util.UUID;
 
-import org.codehaus.jackson.annotate.JsonCreator;
-import org.codehaus.jackson.annotate.JsonProperty;
-import org.codehaus.jackson.map.annotate.JsonView;
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonView;
 
 import com.ning.billing.entitlement.api.timeline.BundleTimeline;
 import com.ning.billing.entitlement.api.timeline.SubscriptionTimeline;
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/BundleTimelineJson.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/BundleTimelineJson.java
index 099d837..11fc814 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/BundleTimelineJson.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/BundleTimelineJson.java
@@ -18,9 +18,9 @@ package com.ning.billing.jaxrs.json;
 
 import java.util.List;
 
-import org.codehaus.jackson.annotate.JsonCreator;
-import org.codehaus.jackson.annotate.JsonProperty;
-import org.codehaus.jackson.map.annotate.JsonView;
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonView;
 
 public class BundleTimelineJson {
 
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/CustomFieldJson.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/CustomFieldJson.java
index cb9e36b..6ba6884 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/CustomFieldJson.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/CustomFieldJson.java
@@ -15,8 +15,9 @@
  */
 package com.ning.billing.jaxrs.json;
 
-import org.codehaus.jackson.annotate.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonCreator;
 
+import com.fasterxml.jackson.annotation.JsonProperty;
 import com.ning.billing.util.customfield.CustomField;
 
 public class CustomFieldJson {
@@ -30,7 +31,8 @@ public class CustomFieldJson {
     }
     
     @JsonCreator
-    public CustomFieldJson(String name, String value) {
+    public CustomFieldJson(@JsonProperty("name") String name,
+                           @JsonProperty("value") String value) {
         super();
         this.name = name;
         this.value = value;
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/InvoiceJsonSimple.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/InvoiceJsonSimple.java
index be2516d..e96179e 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/InvoiceJsonSimple.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/InvoiceJsonSimple.java
@@ -18,9 +18,9 @@ package com.ning.billing.jaxrs.json;
 
 import java.math.BigDecimal;
 
-import org.codehaus.jackson.annotate.JsonCreator;
-import org.codehaus.jackson.annotate.JsonProperty;
-import org.codehaus.jackson.map.annotate.JsonView;
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonView;
 import org.joda.time.DateTime;
 
 import com.ning.billing.invoice.api.Invoice;
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/InvoiceJsonWithBundleKeys.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/InvoiceJsonWithBundleKeys.java
index cc15072..98e2844 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/InvoiceJsonWithBundleKeys.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/InvoiceJsonWithBundleKeys.java
@@ -1,8 +1,8 @@
 package com.ning.billing.jaxrs.json;
 import java.math.BigDecimal;
 
-import org.codehaus.jackson.annotate.JsonCreator;
-import org.codehaus.jackson.annotate.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
 import org.joda.time.DateTime;
 
 import com.ning.billing.invoice.api.Invoice;
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/PaymentJsonSimple.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/PaymentJsonSimple.java
index c0a6d7c..93cd5a0 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/PaymentJsonSimple.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/PaymentJsonSimple.java
@@ -19,9 +19,9 @@ package com.ning.billing.jaxrs.json;
 import java.math.BigDecimal;
 import java.util.UUID;
 
-import org.codehaus.jackson.annotate.JsonCreator;
-import org.codehaus.jackson.annotate.JsonProperty;
-import org.codehaus.jackson.map.annotate.JsonView;
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonView;
 import org.joda.time.DateTime;
 
 import com.ning.billing.util.clock.DefaultClock;
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 e322a59..bd11782 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
@@ -19,8 +19,8 @@ package com.ning.billing.jaxrs.json;
 import java.math.BigDecimal;
 import java.util.UUID;
 
-import org.codehaus.jackson.annotate.JsonCreator;
-import org.codehaus.jackson.annotate.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
 import org.joda.time.DateTime;
 
 public class PaymentJsonWithBundleKeys extends PaymentJsonSimple {
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/SubscriptionJsonNoEvents.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/SubscriptionJsonNoEvents.java
index 95a5e09..c28c6b4 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/SubscriptionJsonNoEvents.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/SubscriptionJsonNoEvents.java
@@ -20,9 +20,9 @@ import java.util.LinkedList;
 import java.util.List;
 import java.util.UUID;
 
-import org.codehaus.jackson.annotate.JsonCreator;
-import org.codehaus.jackson.annotate.JsonProperty;
-import org.codehaus.jackson.map.annotate.JsonView;
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonView;
 import org.joda.time.DateTime;
 
 import com.ning.billing.catalog.api.PlanPhaseSpecifier;
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/SubscriptionJsonSimple.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/SubscriptionJsonSimple.java
index 5fb782e..7d1d018 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/SubscriptionJsonSimple.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/SubscriptionJsonSimple.java
@@ -15,9 +15,9 @@
  */
 package com.ning.billing.jaxrs.json;
 
-import org.codehaus.jackson.annotate.JsonCreator;
-import org.codehaus.jackson.annotate.JsonProperty;
-import org.codehaus.jackson.map.annotate.JsonView;
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonView;
 
 public class SubscriptionJsonSimple {
     
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/SubscriptionJsonWithEvents.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/SubscriptionJsonWithEvents.java
index be5ba2c..27f05e4 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/SubscriptionJsonWithEvents.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/SubscriptionJsonWithEvents.java
@@ -19,9 +19,9 @@ import java.util.LinkedList;
 import java.util.List;
 import java.util.UUID;
 
-import org.codehaus.jackson.annotate.JsonCreator;
-import org.codehaus.jackson.annotate.JsonProperty;
-import org.codehaus.jackson.map.annotate.JsonView;
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonView;
 import org.joda.time.DateTime;
 
 import com.ning.billing.catalog.api.PlanPhaseSpecifier;
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 25ef04c..d620d0f 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
@@ -15,8 +15,8 @@
  */
 package com.ning.billing.jaxrs.json;
 
-import org.codehaus.jackson.annotate.JsonCreator;
-import org.codehaus.jackson.annotate.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
 
 public class TagDefinitionJson {
     
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 8dae3be..3eee26e 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
@@ -21,10 +21,8 @@ import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
 
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.Collections;
 import java.util.LinkedList;
 import java.util.List;
-import java.util.Map;
 import java.util.UUID;
 
 import javax.ws.rs.Consumes;
@@ -46,7 +44,6 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.google.common.base.Function;
-import com.google.common.base.Preconditions;
 import com.google.common.collect.Collections2;
 import com.google.inject.Inject;
 import com.google.inject.Singleton;
@@ -64,7 +61,7 @@ import com.ning.billing.invoice.api.Invoice;
 import com.ning.billing.invoice.api.InvoiceUserApi;
 import com.ning.billing.jaxrs.json.AccountJson;
 import com.ning.billing.jaxrs.json.AccountTimelineJson;
-import com.ning.billing.jaxrs.json.BundleJsonNoSubsciptions;
+import com.ning.billing.jaxrs.json.BundleJsonNoSubscriptions;
 import com.ning.billing.jaxrs.json.CustomFieldJson;
 import com.ning.billing.jaxrs.util.Context;
 import com.ning.billing.jaxrs.util.JaxrsUriBuilder;
@@ -72,31 +69,25 @@ 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.PaymentAttempt;
-import com.ning.billing.util.api.TagDefinitionApiException;
 import com.ning.billing.util.api.TagUserApi;
-import com.ning.billing.util.customfield.CustomField;
-import com.ning.billing.util.customfield.StringCustomField;
-import com.ning.billing.util.tag.Tag;
-import com.ning.billing.util.tag.TagDefinition;
-
 
 @Singleton
-@Path(BaseJaxrsResource.ACCOUNTS_PATH)
-public class AccountResource implements BaseJaxrsResource {
+@Path(JaxrsResource.ACCOUNTS_PATH)
+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 + "/{" + ID_PARAM_NAME + ":" + UUID_PATTERN + "}";
+    private static final String TAG_URI = JaxrsResource.TAGS + "/{" + ID_PARAM_NAME + ":" + UUID_PATTERN + "}";
 
     private final AccountUserApi accountApi;
     private final EntitlementUserApi entitlementApi;
-    private final CustomFieldUserApi customFieldApi;
     private final EntitlementTimelineApi timelineApi;
     private final InvoiceUserApi invoiceApi;
     private final PaymentApi paymentApi;
     private final Context context;
-    private final TagUserApi tagUserApi;
     private final JaxrsUriBuilder uriBuilder;
-    private final TagHelper tagHelper;
-    
+
     @Inject
     public AccountResource(final JaxrsUriBuilder uriBuilder,
             final AccountUserApi accountApi,
@@ -108,16 +99,14 @@ public class AccountResource implements BaseJaxrsResource {
             final TagUserApi tagUserApi,
             final TagHelper tagHelper,
             final Context context) {
+        super(uriBuilder, tagUserApi, tagHelper, customFieldUserApi);
         this.uriBuilder = uriBuilder;
     	this.accountApi = accountApi;
-    	this.tagUserApi = tagUserApi;
         this.entitlementApi = entitlementApi;
-        this.customFieldApi = customFieldUserApi;
         this.invoiceApi = invoiceApi;
         this.paymentApi = paymentApi;
         this.timelineApi = timelineApi;
         this.context = context;
-        this.tagHelper = tagHelper;
     }
 
     @GET
@@ -144,10 +133,10 @@ public class AccountResource implements BaseJaxrsResource {
             accountApi.getAccountById(uuid);
 
             List<SubscriptionBundle> bundles = entitlementApi.getBundlesForAccount(uuid);
-            Collection<BundleJsonNoSubsciptions> result = Collections2.transform(bundles, new Function<SubscriptionBundle, BundleJsonNoSubsciptions>() {
+            Collection<BundleJsonNoSubscriptions> result = Collections2.transform(bundles, new Function<SubscriptionBundle, BundleJsonNoSubscriptions>() {
                 @Override
-                public BundleJsonNoSubsciptions apply(SubscriptionBundle input) {
-                    return new BundleJsonNoSubsciptions(input);
+                public BundleJsonNoSubscriptions apply(SubscriptionBundle input) {
+                    return new BundleJsonNoSubscriptions(input);
                 }
             });
             return Response.status(Status.OK).entity(result).build();
@@ -187,8 +176,7 @@ public class AccountResource implements BaseJaxrsResource {
         try {
             AccountData data = json.toAccountData();
             final Account account = accountApi.createAccount(data, null, null, context.createContext(createdBy, reason, comment));
-            Response response = uriBuilder.buildResponse(AccountResource.class, "getAccount", account.getId());
-            return response;
+            return uriBuilder.buildResponse(AccountResource.class, "getAccount", account.getId());
         } catch (AccountApiException e) {
             final String error = String.format("Failed to create account %s", json);
             log.info(error, e);
@@ -275,162 +263,75 @@ public class AccountResource implements BaseJaxrsResource {
         }
     }
     
-    
-    /****************************      TAGS     ******************************/
-    
     @GET
-    @Path(BaseJaxrsResource.TAGS + "/{accountId:" + UUID_PATTERN + "}")
+    @Path(CUSTOM_FIELD_URI)
     @Produces(APPLICATION_JSON)
-    public Response getAccountTags(@PathParam("accountId") String accountId) {
-        try {
-            Account account = accountApi.getAccountById(UUID.fromString(accountId));
-            Map<String, Tag> tags = tagUserApi.getTags(account.getId(), ObjectType.ACCOUNT);
-            Collection<String> tagNameList = (tags.size() == 0) ?
-                    Collections.<String>emptyList() :
-                Collections2.transform(tags.values(), new Function<Tag, String>() {
-                @Override
-                public String apply(Tag input) {
-                    return input.getTagDefinitionName();
-                }
-            });
-            return Response.status(Status.OK).entity(tagNameList).build();
-        } catch (AccountApiException e) {
-            return Response.status(Status.NO_CONTENT).build();
-        }
+    public Response getCustomFields(@PathParam(ID_PARAM_NAME) final String id) {
+        return super.getCustomFields(UUID.fromString(id));
     }
 
-    
     @POST
-    @Path(BaseJaxrsResource.TAGS + "/{accountId:" + UUID_PATTERN + "}")    
+    @Path(CUSTOM_FIELD_URI)
     @Consumes(APPLICATION_JSON)
     @Produces(APPLICATION_JSON)
-    public Response createAccountTag(@PathParam("accountId") final String accountId,
-            @QueryParam(QUERY_TAGS) final String tagList,
+    public Response createCustomFields(@PathParam(ID_PARAM_NAME) final String id,
+            final List<CustomFieldJson> customFields,
             @HeaderParam(HDR_CREATED_BY) final String createdBy,
             @HeaderParam(HDR_REASON) final String reason,
             @HeaderParam(HDR_COMMENT) final String comment) {
-
-        try {
-            Preconditions.checkNotNull(tagList, "Query % list cannot be null", QUERY_TAGS);
-            
-            Account account = accountApi.getAccountById(UUID.fromString(accountId));
-
-            List<TagDefinition> input = tagHelper.getTagDefinitionFromTagList(tagList);
-            tagUserApi.addTags(account.getId(), ObjectType.ACCOUNT, input, context.createContext(createdBy, reason, comment));
-
-            Response response = uriBuilder.buildResponse(AccountResource.class, "getAccountTags", account.getId());
-            return response;
-        } catch (AccountApiException e) {
-            return Response.status(Status.NO_CONTENT).build();
-        } catch (IllegalArgumentException e) {
-            return Response.status(Status.BAD_REQUEST).entity(e.getMessage()).build();
-        } catch (NullPointerException e) {
-            return Response.status(Status.BAD_REQUEST).entity(e.getMessage()).build();
-        } catch (TagDefinitionApiException e) {
-            return Response.status(Status.BAD_REQUEST).entity(e.getMessage()).build();
-        }
+        return super.createCustomFields(UUID.fromString(id), customFields,
+                context.createContext(createdBy, reason, comment));
     }
     
     @DELETE
-    @Path(BaseJaxrsResource.TAGS +  "/{accountId:" + UUID_PATTERN + "}")    
+    @Path(CUSTOM_FIELD_URI)
     @Consumes(APPLICATION_JSON)
     @Produces(APPLICATION_JSON)
-    public Response deleteAccountTag(@PathParam("accountId") final String accountId,
-            @QueryParam(QUERY_TAGS) final String tagList,
+    public Response deleteCustomFields(@PathParam(ID_PARAM_NAME) final String id,
+            @QueryParam(QUERY_CUSTOM_FIELDS) final String customFieldList,
             @HeaderParam(HDR_CREATED_BY) final String createdBy,
             @HeaderParam(HDR_REASON) final String reason,
             @HeaderParam(HDR_COMMENT) final String comment) {
-
-        try {
-            Account account = accountApi.getAccountById(UUID.fromString(accountId));
-
-            List<TagDefinition> input = tagHelper.getTagDefinitionFromTagList(tagList);
-            tagUserApi.removeTags(account.getId(), ObjectType.ACCOUNT, input, context.createContext(createdBy, reason, comment));
-
-            return Response.status(Status.OK).build();
-        } catch (AccountApiException e) {
-            return Response.status(Status.NO_CONTENT).build();
-        } catch (IllegalArgumentException e) {
-            return Response.status(Status.BAD_REQUEST).entity(e.getMessage()).build();
-        } catch (NullPointerException e) {
-            return Response.status(Status.BAD_REQUEST).entity(e.getMessage()).build();
-        } catch (TagDefinitionApiException e) {
-            return Response.status(Status.BAD_REQUEST).entity(e.getMessage()).build();
-        }
+        return super.deleteCustomFields(UUID.fromString(id), customFieldList,
+                context.createContext(createdBy, reason, comment));
     }
-    
-    /************************   CUSTOM FIELDS   ******************************/
-    
+
     @GET
-    @Path(BaseJaxrsResource.CUSTOM_FIELDS + "/{accountId:" + UUID_PATTERN + "}")
+    @Path(TAG_URI)
     @Produces(APPLICATION_JSON)
-    public Response getAccountCustomFields(@PathParam("accountId") String accountId) {
-        try {
-            Account account = accountApi.getAccountById(UUID.fromString(accountId));
-            Map<String, CustomField> fields = customFieldApi.getCustomFields(account.getId(), ObjectType.ACCOUNT);
-
-            List<CustomFieldJson> result = new LinkedList<CustomFieldJson>();
-            for (CustomField cur : fields.values()) {
-                result.add(new CustomFieldJson(cur));
-            }
-            return Response.status(Status.OK).entity(result).build();
-        } catch (AccountApiException e) {
-            return Response.status(Status.NO_CONTENT).build();
-        }
+    public Response getTags(@PathParam(ID_PARAM_NAME) String id) {
+        return super.getTags(UUID.fromString(id));
     }
-    
-    
+
     @POST
-    @Path(BaseJaxrsResource.CUSTOM_FIELDS + "/{accountId:" + UUID_PATTERN + "}")    
+    @Path(TAG_URI)
     @Consumes(APPLICATION_JSON)
     @Produces(APPLICATION_JSON)
-    public Response createCustomField(@PathParam("accountId") final String accountId,
-            List<CustomFieldJson> customFields,
+    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) {
-
-        try {
-            
-            Account account = accountApi.getAccountById(UUID.fromString(accountId));
-            LinkedList<CustomField> input = new LinkedList<CustomField>();
-            for (CustomFieldJson cur : customFields) {
-                input.add(new StringCustomField(cur.getName(), cur.getValue()));
-            }
-
-            customFieldApi.saveCustomFields(account.getId(), ObjectType.ACCOUNT, input, context.createContext(createdBy, reason, comment));
-            Response response = uriBuilder.buildResponse(AccountResource.class, "getAccountCustomFields", account.getId());            
-            return response;
-        } catch (AccountApiException e) {
-            return Response.status(Status.NO_CONTENT).build();
-        } catch (IllegalArgumentException e) {
-            return Response.status(Status.BAD_REQUEST).entity(e.getMessage()).build();
-        } catch (NullPointerException e) {
-            return Response.status(Status.BAD_REQUEST).entity(e.getMessage()).build();
-        }
+        return super.createTags(UUID.fromString(id), tagList,
+                                context.createContext(createdBy, reason, comment));
     }
-    
+
     @DELETE
-    @Path(BaseJaxrsResource.CUSTOM_FIELDS +  "/{accountId:" + UUID_PATTERN + "}")    
+    @Path(TAG_URI)
     @Consumes(APPLICATION_JSON)
     @Produces(APPLICATION_JSON)
-    public Response deleteCustomFields(@PathParam("accountId") final String accountId,
-            @QueryParam(QUERY_CUSTOM_FIELDS) final String customFieldList,
+    public Response deleteTags(@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) {
 
-        try {
-            Account account = accountApi.getAccountById(UUID.fromString(accountId));
-            // STEPH missing API to delete custom fields
-            return Response.status(Status.OK).build();
-        } catch (AccountApiException e) {
-            return Response.status(Status.NO_CONTENT).build();
-        } catch (IllegalArgumentException e) {
-            return Response.status(Status.BAD_REQUEST).entity(e.getMessage()).build();
-        } catch (NullPointerException e) {
-            return Response.status(Status.BAD_REQUEST).entity(e.getMessage()).build();
-        }
+        return super.deleteTags(UUID.fromString(id), tagList,
+                                context.createContext(createdBy, reason, comment));
+    }
+
+    @Override
+    protected ObjectType getObjectType() {
+        return ObjectType.ACCOUNT;
     }
-    
 }
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 e62d48e..f2d64a5 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
@@ -23,6 +23,7 @@ import java.util.List;
 import java.util.UUID;
 
 import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
 import javax.ws.rs.GET;
 import javax.ws.rs.HeaderParam;
 import javax.ws.rs.POST;
@@ -33,6 +34,11 @@ import javax.ws.rs.QueryParam;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.Response.Status;
 
+import com.ning.billing.jaxrs.json.CustomFieldJson;
+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;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -44,22 +50,28 @@ import com.ning.billing.entitlement.api.user.EntitlementUserApi;
 import com.ning.billing.entitlement.api.user.EntitlementUserApiException;
 import com.ning.billing.entitlement.api.user.Subscription;
 import com.ning.billing.entitlement.api.user.SubscriptionBundle;
-import com.ning.billing.jaxrs.json.BundleJsonNoSubsciptions;
+import com.ning.billing.jaxrs.json.BundleJsonNoSubscriptions;
 import com.ning.billing.jaxrs.json.SubscriptionJsonNoEvents;
 import com.ning.billing.jaxrs.util.Context;
 import com.ning.billing.jaxrs.util.JaxrsUriBuilder;
 
-@Path(BaseJaxrsResource.BUNDLES_PATH)
-public class BundleResource implements BaseJaxrsResource {
+@Path(JaxrsResource.BUNDLES_PATH)
+public class BundleResource extends JaxRsResourceBase {
 
     private static final Logger log = LoggerFactory.getLogger(BundleResource.class);
+    private static final String ID_PARAM_NAME = "bundleId";
+    private static final String CUSTOM_FIELD_URI = JaxrsResource.CUSTOM_FIELDS + "/{" + ID_PARAM_NAME + ":" + UUID_PATTERN + "}";
+    private static final String TAG_URI = JaxrsResource.TAGS + "/{" + ID_PARAM_NAME + ":" + UUID_PATTERN + "}";
 
     private final EntitlementUserApi entitlementApi;
     private final Context context;
-    private final JaxrsUriBuilder uriBuilder;	
+    private final JaxrsUriBuilder uriBuilder;
 
     @Inject
-    public BundleResource(final JaxrsUriBuilder uriBuilder, final EntitlementUserApi entitlementApi, final Context context) {
+    public BundleResource(final JaxrsUriBuilder uriBuilder, final EntitlementUserApi entitlementApi,
+                          TagUserApi tagUserApi, TagHelper tagHelper, CustomFieldUserApi customFieldUserApi,
+                          Context context) {
+        super(uriBuilder, tagUserApi, tagHelper, customFieldUserApi);
         this.uriBuilder = uriBuilder;
         this.entitlementApi = entitlementApi;
         this.context = context;
@@ -71,7 +83,7 @@ public class BundleResource implements BaseJaxrsResource {
     public Response getBundle(@PathParam("bundleId") final String bundleId) throws EntitlementUserApiException {
         try {
             SubscriptionBundle bundle = entitlementApi.getBundleFromId(UUID.fromString(bundleId));
-            BundleJsonNoSubsciptions json = new BundleJsonNoSubsciptions(bundle);
+            BundleJsonNoSubscriptions json = new BundleJsonNoSubscriptions(bundle);
             return Response.status(Status.OK).entity(json).build();
         } catch (EntitlementUserApiException e) {
             if (e.getCode() == ErrorCode.ENT_GET_INVALID_BUNDLE_ID.getCode()) {
@@ -88,7 +100,7 @@ public class BundleResource implements BaseJaxrsResource {
     public Response getBundleByKey(@QueryParam(QUERY_EXTERNAL_KEY) final String externalKey) throws EntitlementUserApiException {
         try {
             SubscriptionBundle bundle = entitlementApi.getBundleForKey(externalKey);
-            BundleJsonNoSubsciptions json = new BundleJsonNoSubsciptions(bundle);
+            BundleJsonNoSubscriptions json = new BundleJsonNoSubscriptions(bundle);
             return Response.status(Status.OK).entity(json).build();
         } catch (EntitlementUserApiException e) {
             if (e.getCode() == ErrorCode.ENT_GET_INVALID_BUNDLE_KEY.getCode()) {
@@ -103,7 +115,7 @@ public class BundleResource implements BaseJaxrsResource {
     @POST
     @Consumes(APPLICATION_JSON)
     @Produces(APPLICATION_JSON)
-    public Response createBundle(final BundleJsonNoSubsciptions json,
+    public Response createBundle(final BundleJsonNoSubscriptions json,
             @HeaderParam(HDR_CREATED_BY) final String createdBy,
             @HeaderParam(HDR_REASON) final String reason,
             @HeaderParam(HDR_COMMENT) final String comment) {
@@ -147,4 +159,76 @@ public class BundleResource implements BaseJaxrsResource {
 
         }
     }
+
+    @GET
+    @Path(CUSTOM_FIELD_URI)
+    @Produces(APPLICATION_JSON)
+    public Response getCustomFields(@PathParam(ID_PARAM_NAME) final String id) {
+        return super.getCustomFields(UUID.fromString(id));
+    }
+
+    @POST
+    @Path(CUSTOM_FIELD_URI)
+    @Consumes(APPLICATION_JSON)
+    @Produces(APPLICATION_JSON)
+    public Response createCustomFields(@PathParam(ID_PARAM_NAME) final String id,
+            final List<CustomFieldJson> customFields,
+            @HeaderParam(HDR_CREATED_BY) final String createdBy,
+            @HeaderParam(HDR_REASON) final String reason,
+            @HeaderParam(HDR_COMMENT) final String comment) {
+        return super.createCustomFields(UUID.fromString(id), customFields,
+                context.createContext(createdBy, reason, comment));
+    }
+
+    @DELETE
+    @Path(CUSTOM_FIELD_URI)
+    @Consumes(APPLICATION_JSON)
+    @Produces(APPLICATION_JSON)
+    public Response deleteCustomFields(@PathParam(ID_PARAM_NAME) final String id,
+            @QueryParam(QUERY_CUSTOM_FIELDS) final String customFieldList,
+            @HeaderParam(HDR_CREATED_BY) final String createdBy,
+            @HeaderParam(HDR_REASON) final String reason,
+            @HeaderParam(HDR_COMMENT) final String comment) {
+        return super.deleteCustomFields(UUID.fromString(id), customFieldList,
+                context.createContext(createdBy, reason, comment));
+    }
+
+    @GET
+    @Path(TAG_URI)
+    @Produces(APPLICATION_JSON)
+    public Response getTags(@PathParam(ID_PARAM_NAME) String id) {
+        return super.getTags(UUID.fromString(id));
+    }
+
+    @POST
+    @Path(TAG_URI)
+    @Consumes(APPLICATION_JSON)
+    @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,
+                                context.createContext(createdBy, reason, comment));
+    }
+
+    @DELETE
+    @Path(TAG_URI)
+    @Consumes(APPLICATION_JSON)
+    @Produces(APPLICATION_JSON)
+    public Response deleteTags(@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.deleteTags(UUID.fromString(id), tagList,
+                                context.createContext(createdBy, reason, comment));
+    }
+
+    @Override
+    protected ObjectType getObjectType() {
+        return ObjectType.BUNDLE;
+    }
 }
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 fd2ec57..0081a16 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
@@ -23,6 +23,7 @@ import java.util.List;
 import java.util.UUID;
 
 import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
 import javax.ws.rs.DefaultValue;
 import javax.ws.rs.GET;
 import javax.ws.rs.HeaderParam;
@@ -35,6 +36,11 @@ import javax.ws.rs.QueryParam;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.Response.Status;
 
+import com.ning.billing.jaxrs.json.CustomFieldJson;
+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;
 import org.joda.time.DateTime;
 import org.joda.time.format.DateTimeFormatter;
 import org.joda.time.format.ISODateTimeFormat;
@@ -54,11 +60,12 @@ import com.ning.billing.jaxrs.util.Context;
 import com.ning.billing.jaxrs.util.JaxrsUriBuilder;
 
 
-@Path(BaseJaxrsResource.INVOICES_PATH)
-public class InvoiceResource implements BaseJaxrsResource {
-
-
+@Path(JaxrsResource.INVOICES_PATH)
+public class InvoiceResource extends JaxRsResourceBase {
     private static final Logger log = LoggerFactory.getLogger(InvoiceResource.class);
+    private static final String ID_PARAM_NAME = "invoiceId";
+    private static final String CUSTOM_FIELD_URI = JaxrsResource.CUSTOM_FIELDS + "/{" + ID_PARAM_NAME + ":" + UUID_PATTERN + "}";
+    private static final String TAG_URI = JaxrsResource.TAGS + "/{" + ID_PARAM_NAME + ":" + UUID_PATTERN + "}";
 
     private final DateTimeFormatter DATE_TIME_FORMATTER = ISODateTimeFormat.dateTime();
     
@@ -71,7 +78,11 @@ public class InvoiceResource implements BaseJaxrsResource {
     public InvoiceResource(final AccountUserApi accountApi,
             final InvoiceUserApi invoiceApi,
             final Context context,
-            final JaxrsUriBuilder uriBuilder) {
+            final JaxrsUriBuilder uriBuilder,
+            final TagUserApi tagUserApi,
+            final TagHelper tagHelper,
+            final CustomFieldUserApi customFieldUserApi) {
+        super(uriBuilder, tagUserApi, tagHelper, customFieldUserApi);
         this.accountApi = accountApi;
         this.invoiceApi = invoiceApi;
         this.context = context;
@@ -141,4 +152,76 @@ public class InvoiceResource implements BaseJaxrsResource {
             return Response.status(Status.BAD_REQUEST).entity(e.getMessage()).build();            
         }
     }
+
+    @GET
+    @Path(CUSTOM_FIELD_URI)
+    @Produces(APPLICATION_JSON)
+    public Response getCustomFields(@PathParam(ID_PARAM_NAME) final String id) {
+        return super.getCustomFields(UUID.fromString(id));
+    }
+
+    @POST
+    @Path(CUSTOM_FIELD_URI)
+    @Consumes(APPLICATION_JSON)
+    @Produces(APPLICATION_JSON)
+    public Response createCustomFields(@PathParam(ID_PARAM_NAME) final String id,
+            final List<CustomFieldJson> customFields,
+            @HeaderParam(HDR_CREATED_BY) final String createdBy,
+            @HeaderParam(HDR_REASON) final String reason,
+            @HeaderParam(HDR_COMMENT) final String comment) {
+        return super.createCustomFields(UUID.fromString(id), customFields,
+                context.createContext(createdBy, reason, comment));
+    }
+
+    @DELETE
+    @Path(CUSTOM_FIELD_URI)
+    @Consumes(APPLICATION_JSON)
+    @Produces(APPLICATION_JSON)
+    public Response deleteCustomFields(@PathParam(ID_PARAM_NAME) final String id,
+            @QueryParam(QUERY_CUSTOM_FIELDS) final String customFieldList,
+            @HeaderParam(HDR_CREATED_BY) final String createdBy,
+            @HeaderParam(HDR_REASON) final String reason,
+            @HeaderParam(HDR_COMMENT) final String comment) {
+        return super.deleteCustomFields(UUID.fromString(id), customFieldList,
+                context.createContext(createdBy, reason, comment));
+    }
+
+    @GET
+    @Path(TAG_URI)
+    @Produces(APPLICATION_JSON)
+    public Response getTags(@PathParam(ID_PARAM_NAME) String id) {
+        return super.getTags(UUID.fromString(id));
+    }
+
+    @POST
+    @Path(TAG_URI)
+    @Consumes(APPLICATION_JSON)
+    @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,
+                                context.createContext(createdBy, reason, comment));
+    }
+
+    @DELETE
+    @Path(TAG_URI)
+    @Consumes(APPLICATION_JSON)
+    @Produces(APPLICATION_JSON)
+    public Response deleteTags(@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.deleteTags(UUID.fromString(id), tagList,
+                                context.createContext(createdBy, reason, comment));
+    }
+
+    @Override
+    protected ObjectType getObjectType() {
+        return ObjectType.INVOICE;
+    }
 }
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
new file mode 100644
index 0000000..a302336
--- /dev/null
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/JaxRsResourceBase.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.jaxrs.resources;
+
+import com.google.common.base.Function;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Collections2;
+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.TagDefinitionApiException;
+import com.ning.billing.util.api.TagUserApi;
+import com.ning.billing.util.callcontext.CallContext;
+import com.ning.billing.util.customfield.CustomField;
+import com.ning.billing.util.customfield.StringCustomField;
+import com.ning.billing.util.dao.ObjectType;
+import com.ning.billing.util.tag.Tag;
+import com.ning.billing.util.tag.TagDefinition;
+
+import javax.ws.rs.core.Response;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+public abstract class JaxRsResourceBase implements JaxrsResource {
+    private final JaxrsUriBuilder uriBuilder;
+    private final TagUserApi tagUserApi;
+    private final TagHelper tagHelper;
+    private 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) {
+        Map<String, Tag> tags = tagUserApi.getTags(id, getObjectType());
+        Collection<String> tagNameList = (tags.size() == 0) ?
+                Collections.<String>emptyList() :
+            Collections2.transform(tags.values(), new Function<Tag, String>() {
+                @Override
+                public String apply(Tag input) {
+                    return input.getTagDefinitionName();
+                }
+            });
+        return Response.status(Response.Status.OK).entity(tagNameList).build();
+    }
+
+    protected Response createTags(final UUID id,
+                                  final String tagList,
+                                  final CallContext context) {
+        try {
+            Preconditions.checkNotNull(tagList, "Query % list cannot be null", JaxrsResource.QUERY_TAGS);
+
+            List<TagDefinition> input = tagHelper.getTagDefinitionFromTagList(tagList);
+            tagUserApi.addTags(id, getObjectType(), input, context);
+
+            return uriBuilder.buildResponse(this.getClass(), "createTags", id);
+        } 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();
+        }
+    }
+
+    protected Response deleteTags(final UUID id,
+                                  final String tagList,
+                                  final CallContext context) {
+
+        try {
+            List<TagDefinition> input = tagHelper.getTagDefinitionFromTagList(tagList);
+            tagUserApi.removeTags(id, getObjectType(), input, context);
+
+            return Response.status(Response.Status.OK).build();
+        } 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();
+        }
+    }
+
+    protected Response getCustomFields(final UUID id) {
+        Map<String, CustomField> fields = customFieldUserApi.getCustomFields(id, getObjectType());
+
+        List<CustomFieldJson> result = new LinkedList<CustomFieldJson>();
+        for (CustomField cur : fields.values()) {
+            result.add(new CustomFieldJson(cur));
+        }
+        return Response.status(Response.Status.OK).entity(result).build();
+    }
+
+    protected Response createCustomFields(final UUID id,
+                                          final List<CustomFieldJson> customFields,
+                                          final CallContext context) {
+        try {
+            LinkedList<CustomField> input = new LinkedList<CustomField>();
+            for (CustomFieldJson cur : customFields) {
+                input.add(new StringCustomField(cur.getName(), cur.getValue()));
+            }
+
+            customFieldUserApi.saveCustomFields(id, getObjectType(), input, context);
+            return uriBuilder.buildResponse(this.getClass(), "createCustomFields", id);
+        } 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();
+        }
+    }
+
+    protected Response deleteCustomFields(final UUID id,
+                                          final String customFieldList,
+                                          final CallContext context) {
+        try {
+            // STEPH missing API to delete custom fields
+            return Response.status(Response.Status.OK).build();
+        } 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();
+        }
+    }
+}
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 2988f5a..5736bc0 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
@@ -19,7 +19,9 @@ package com.ning.billing.jaxrs.resources;
 import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
 
 import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
 import javax.ws.rs.GET;
+import javax.ws.rs.HeaderParam;
 import javax.ws.rs.POST;
 import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
@@ -28,12 +30,34 @@ import javax.ws.rs.QueryParam;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.Response.Status;
 
+import com.google.inject.Inject;
+import com.ning.billing.jaxrs.json.CustomFieldJson;
 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.util.api.CustomFieldUserApi;
+import com.ning.billing.util.api.TagUserApi;
+import com.ning.billing.util.dao.ObjectType;
 
+import java.util.List;
+import java.util.UUID;
 
 @Path("/1.0/payment")
-public class PaymentResource {
+public class PaymentResource extends JaxRsResourceBase {
+    private static final String ID_PARAM_NAME = "paymentId";
+    private static final String CUSTOM_FIELD_URI = JaxrsResource.CUSTOM_FIELDS + "/{" + ID_PARAM_NAME + ":" + UUID_PATTERN + "}";
+    private static final String TAG_URI = JaxrsResource.TAGS + "/{" + ID_PARAM_NAME + ":" + UUID_PATTERN + "}";
 
+    private final Context context;
+
+    @Inject
+    public PaymentResource(final JaxrsUriBuilder uriBuilder, final TagUserApi tagUserApi,
+                           final TagHelper tagHelper, final CustomFieldUserApi customFieldUserApi,
+                           final Context context) {
+        super(uriBuilder, tagUserApi, tagHelper, customFieldUserApi);
+        this.context = context;
+    }
 
     @GET
     @Path("/{invoiceId:\\w+-\\w+-\\w+-\\w+-\\w+}")
@@ -59,4 +83,76 @@ public class PaymentResource {
             @QueryParam("nameOnCC") String nameOnCC) {
         return Response.status(Status.INTERNAL_SERVER_ERROR).build();
     }
+
+    @GET
+    @Path(CUSTOM_FIELD_URI)
+    @Produces(APPLICATION_JSON)
+    public Response getCustomFields(@PathParam(ID_PARAM_NAME) final String id) {
+        return super.getCustomFields(UUID.fromString(id));
+    }
+
+    @POST
+    @Path(CUSTOM_FIELD_URI)
+    @Consumes(APPLICATION_JSON)
+    @Produces(APPLICATION_JSON)
+    public Response createCustomFields(@PathParam(ID_PARAM_NAME) final String id,
+            final List<CustomFieldJson> customFields,
+            @HeaderParam(HDR_CREATED_BY) final String createdBy,
+            @HeaderParam(HDR_REASON) final String reason,
+            @HeaderParam(HDR_COMMENT) final String comment) {
+        return super.createCustomFields(UUID.fromString(id), customFields,
+                context.createContext(createdBy, reason, comment));
+    }
+
+    @DELETE
+    @Path(CUSTOM_FIELD_URI)
+    @Consumes(APPLICATION_JSON)
+    @Produces(APPLICATION_JSON)
+    public Response deleteCustomFields(@PathParam(ID_PARAM_NAME) final String id,
+            @QueryParam(QUERY_CUSTOM_FIELDS) final String customFieldList,
+            @HeaderParam(HDR_CREATED_BY) final String createdBy,
+            @HeaderParam(HDR_REASON) final String reason,
+            @HeaderParam(HDR_COMMENT) final String comment) {
+        return super.deleteCustomFields(UUID.fromString(id), customFieldList,
+                context.createContext(createdBy, reason, comment));
+    }
+
+    @GET
+    @Path(TAG_URI)
+    @Produces(APPLICATION_JSON)
+    public Response getTags(@PathParam(ID_PARAM_NAME) String id) {
+        return super.getTags(UUID.fromString(id));
+    }
+
+    @POST
+    @Path(TAG_URI)
+    @Consumes(APPLICATION_JSON)
+    @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,
+                                context.createContext(createdBy, reason, comment));
+    }
+
+    @DELETE
+    @Path(TAG_URI)
+    @Consumes(APPLICATION_JSON)
+    @Produces(APPLICATION_JSON)
+    public Response deleteTags(@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.deleteTags(UUID.fromString(id), tagList,
+                                context.createContext(createdBy, reason, comment));
+    }
+
+    @Override
+    protected ObjectType getObjectType() {
+        return ObjectType.PAYMENT;
+    }
 }
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 67c5b5c..88b2de7 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
@@ -19,6 +19,7 @@ package com.ning.billing.jaxrs.resources;
 import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
 
 import java.math.BigDecimal;
+import java.util.List;
 import java.util.UUID;
 import java.util.concurrent.TimeoutException;
 
@@ -36,6 +37,11 @@ import javax.ws.rs.QueryParam;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.Response.Status;
 
+import com.ning.billing.jaxrs.json.CustomFieldJson;
+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;
 import org.joda.time.DateTime;
 import org.joda.time.format.DateTimeFormatter;
 import org.joda.time.format.ISODateTimeFormat;
@@ -60,13 +66,14 @@ import com.ning.billing.jaxrs.util.KillbillEventHandler;
 import com.ning.billing.payment.api.PaymentErrorEvent;
 import com.ning.billing.payment.api.PaymentInfoEvent;
 import com.ning.billing.util.callcontext.CallContext;
-import com.ning.billing.util.clock.Clock;
 import com.ning.billing.util.userrequest.CompletionUserRequestBase;
 
-@Path(BaseJaxrsResource.SUBSCRIPTIONS_PATH)
-public class SubscriptionResource implements BaseJaxrsResource {
-
+@Path(JaxrsResource.SUBSCRIPTIONS_PATH)
+public class SubscriptionResource extends JaxRsResourceBase {
     private static final Logger log = LoggerFactory.getLogger(SubscriptionResource.class);
+    private static final String ID_PARAM_NAME = "subscriptionId";
+    private static final String CUSTOM_FIELD_URI = JaxrsResource.CUSTOM_FIELDS + "/{" + ID_PARAM_NAME + ":" + UUID_PATTERN + "}";
+    private static final String TAG_URI = JaxrsResource.TAGS + "/{" + ID_PARAM_NAME + ":" + UUID_PATTERN + "}";
 
     private final DateTimeFormatter DATE_TIME_FORMATTER = ISODateTimeFormat.dateTime();
 
@@ -77,7 +84,9 @@ public class SubscriptionResource implements BaseJaxrsResource {
     
     @Inject
     public SubscriptionResource(final JaxrsUriBuilder uriBuilder, final EntitlementUserApi entitlementApi,
-            final Clock clock, final Context context, final KillbillEventHandler killbillHandler) {
+            final Context context, final KillbillEventHandler killbillHandler,
+            final TagUserApi tagUserApi, final TagHelper tagHelper, final CustomFieldUserApi customFieldUserApi) {
+        super(uriBuilder, tagUserApi, tagHelper, customFieldUserApi);
         this.uriBuilder = uriBuilder;
         this.entitlementApi = entitlementApi;
         this.context = context;
@@ -342,4 +351,76 @@ public class SubscriptionResource implements BaseJaxrsResource {
             }
         }
     }
+
+    @GET
+    @Path(CUSTOM_FIELD_URI)
+    @Produces(APPLICATION_JSON)
+    public Response getCustomFields(@PathParam(ID_PARAM_NAME) final String id) {
+        return super.getCustomFields(UUID.fromString(id));
+    }
+
+    @POST
+    @Path(CUSTOM_FIELD_URI)
+    @Consumes(APPLICATION_JSON)
+    @Produces(APPLICATION_JSON)
+    public Response createCustomFields(@PathParam(ID_PARAM_NAME) final String id,
+            final List<CustomFieldJson> customFields,
+            @HeaderParam(HDR_CREATED_BY) final String createdBy,
+            @HeaderParam(HDR_REASON) final String reason,
+            @HeaderParam(HDR_COMMENT) final String comment) {
+        return super.createCustomFields(UUID.fromString(id), customFields,
+                context.createContext(createdBy, reason, comment));
+    }
+
+    @DELETE
+    @Path(CUSTOM_FIELD_URI)
+    @Consumes(APPLICATION_JSON)
+    @Produces(APPLICATION_JSON)
+    public Response deleteCustomFields(@PathParam(ID_PARAM_NAME) final String id,
+            @QueryParam(QUERY_CUSTOM_FIELDS) final String customFieldList,
+            @HeaderParam(HDR_CREATED_BY) final String createdBy,
+            @HeaderParam(HDR_REASON) final String reason,
+            @HeaderParam(HDR_COMMENT) final String comment) {
+        return super.deleteCustomFields(UUID.fromString(id), customFieldList,
+                context.createContext(createdBy, reason, comment));
+    }
+
+    @GET
+    @Path(TAG_URI)
+    @Produces(APPLICATION_JSON)
+    public Response getTags(@PathParam(ID_PARAM_NAME) String id) {
+        return super.getTags(UUID.fromString(id));
+    }
+
+    @POST
+    @Path(TAG_URI)
+    @Consumes(APPLICATION_JSON)
+    @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,
+                                context.createContext(createdBy, reason, comment));
+    }
+
+    @DELETE
+    @Path(TAG_URI)
+    @Consumes(APPLICATION_JSON)
+    @Produces(APPLICATION_JSON)
+    public Response deleteTags(@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.deleteTags(UUID.fromString(id), tagList,
+                                context.createContext(createdBy, reason, comment));
+    }
+
+    @Override
+    protected ObjectType getObjectType() {
+        return ObjectType.SUBSCRIPTION;
+    }
 }
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 3111240..0e3853c 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
@@ -42,8 +42,8 @@ import com.ning.billing.util.api.TagUserApi;
 import com.ning.billing.util.tag.TagDefinition;
 
 @Singleton
-@Path(BaseJaxrsResource.TAG_DEFINITIONS_PATH)
-public class TagResource implements BaseJaxrsResource {
+@Path(JaxrsResource.TAG_DEFINITIONS_PATH)
+public class TagResource implements JaxrsResource {
     
     private final TagUserApi tagUserApi;
     private final Context context;
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/util/Context.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/util/Context.java
index 729f166..f6b7d67 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/util/Context.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/util/Context.java
@@ -19,7 +19,7 @@ import java.util.UUID;
 
 import com.google.common.base.Preconditions;
 import com.google.inject.Inject;
-import com.ning.billing.jaxrs.resources.BaseJaxrsResource;
+import com.ning.billing.jaxrs.resources.JaxrsResource;
 import com.ning.billing.util.callcontext.CallContext;
 import com.ning.billing.util.callcontext.CallContextFactory;
 import com.ning.billing.util.callcontext.CallOrigin;
@@ -42,7 +42,7 @@ public class Context {
     public CallContext createContext(final String createdBy, final String reason, final String comment)
     throws IllegalArgumentException {
         try {
-            Preconditions.checkNotNull(createdBy, String.format("Header %s needs to be set", BaseJaxrsResource.HDR_CREATED_BY));
+            Preconditions.checkNotNull(createdBy, String.format("Header %s needs to be set", JaxrsResource.HDR_CREATED_BY));
             return contextFactory.createCallContext(createdBy, origin, userType, UUID.randomUUID());
         } catch (NullPointerException e) {
             throw new IllegalArgumentException(e.getMessage());
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/util/JaxrsUriBuilder.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/util/JaxrsUriBuilder.java
index b351b4c..0917106 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/util/JaxrsUriBuilder.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/util/JaxrsUriBuilder.java
@@ -16,17 +16,16 @@
 package com.ning.billing.jaxrs.util;
 
 import java.net.URI;
-import java.util.UUID;
 
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.UriBuilder;
 
-import com.ning.billing.jaxrs.resources.BaseJaxrsResource;
+import com.ning.billing.jaxrs.resources.JaxrsResource;
 
 public class JaxrsUriBuilder {
 
 	
-	public Response buildResponse(final Class<? extends BaseJaxrsResource> theClass, final String getMethodName, final Object objectId) {
+	public Response buildResponse(final Class<? extends JaxrsResource> theClass, final String getMethodName, final Object objectId) {
 		URI uri = UriBuilder.fromPath(objectId.toString()).build();
 		Response.ResponseBuilder ri = Response.created(uri);
 		return ri.entity(new Object() {

junction/pom.xml 2(+1 -1)

diff --git a/junction/pom.xml b/junction/pom.xml
index 3ff7f0a..4efa966 100644
--- a/junction/pom.xml
+++ b/junction/pom.xml
@@ -13,7 +13,7 @@
     <parent>
         <groupId>com.ning.billing</groupId>
         <artifactId>killbill</artifactId>
-        <version>0.1.12-SNAPSHOT</version>
+        <version>0.1.13-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <artifactId>killbill-junction</artifactId>
diff --git a/junction/src/test/java/com/ning/billing/junction/blocking/TestBlockingChecker.java b/junction/src/test/java/com/ning/billing/junction/blocking/TestBlockingChecker.java
index 0bff4da..1d70eac 100644
--- a/junction/src/test/java/com/ning/billing/junction/blocking/TestBlockingChecker.java
+++ b/junction/src/test/java/com/ning/billing/junction/blocking/TestBlockingChecker.java
@@ -19,7 +19,6 @@ package com.ning.billing.junction.blocking;
 import java.util.SortedSet;
 import java.util.UUID;
 
-import org.apache.commons.lang.NotImplementedException;
 import org.testng.Assert;
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.Test;
@@ -42,7 +41,6 @@ import com.ning.billing.mock.BrainDeadProxyFactory;
 import com.ning.billing.mock.BrainDeadProxyFactory.ZombieControl;
 import com.ning.billing.util.clock.Clock;
 
-
 public class TestBlockingChecker {
    
     private BlockingState bundleState;
@@ -75,17 +73,17 @@ public class TestBlockingChecker {
 
         @Override
         public SortedSet<BlockingState> getBlockingHistoryFor(Blockable overdueable) {
-            throw new NotImplementedException();
+            throw new UnsupportedOperationException();
         }
 
         @Override
         public SortedSet<BlockingState> getBlockingHistoryFor(UUID overdueableId) {
-            throw new NotImplementedException();
+            throw new UnsupportedOperationException();
         }
 
         @Override
         public <T extends Blockable> void setBlockingState(BlockingState state, Clock clock) {
-            throw new NotImplementedException();
+            throw new UnsupportedOperationException();
         }
         
     };
diff --git a/junction/src/test/java/com/ning/billing/junction/plumbing/billing/MockSubscriptionEvent.java b/junction/src/test/java/com/ning/billing/junction/plumbing/billing/MockSubscriptionEvent.java
index cbba255..90f610f 100644
--- a/junction/src/test/java/com/ning/billing/junction/plumbing/billing/MockSubscriptionEvent.java
+++ b/junction/src/test/java/com/ning/billing/junction/plumbing/billing/MockSubscriptionEvent.java
@@ -17,15 +17,14 @@ package com.ning.billing.junction.plumbing.billing;
 
 import java.util.UUID;
 
-import org.codehaus.jackson.annotate.JsonCreator;
-import org.codehaus.jackson.annotate.JsonIgnore;
-import org.codehaus.jackson.annotate.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
 import org.joda.time.DateTime;
 
 import com.ning.billing.entitlement.api.SubscriptionTransitionType;
 import com.ning.billing.entitlement.api.user.Subscription.SubscriptionState;
 import com.ning.billing.entitlement.api.user.SubscriptionEvent;
-import com.ning.billing.util.bus.BusEvent.BusEventType;
 
 public class MockSubscriptionEvent implements SubscriptionEvent {
 

overdue/pom.xml 2(+1 -1)

diff --git a/overdue/pom.xml b/overdue/pom.xml
index 405ab76..d421155 100644
--- a/overdue/pom.xml
+++ b/overdue/pom.xml
@@ -13,7 +13,7 @@
     <parent>
         <groupId>com.ning.billing</groupId>
         <artifactId>killbill</artifactId>
-        <version>0.1.12-SNAPSHOT</version>
+        <version>0.1.13-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <artifactId>killbill-overdue</artifactId>
diff --git a/overdue/src/main/java/com/ning/billing/overdue/api/DefaultOverdueUserApi.java b/overdue/src/main/java/com/ning/billing/overdue/api/DefaultOverdueUserApi.java
index acc9b85..5979869 100644
--- a/overdue/src/main/java/com/ning/billing/overdue/api/DefaultOverdueUserApi.java
+++ b/overdue/src/main/java/com/ning/billing/overdue/api/DefaultOverdueUserApi.java
@@ -16,7 +16,6 @@
 
 package com.ning.billing.overdue.api;
 
-import org.apache.commons.lang.NotImplementedException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -81,7 +80,7 @@ public class DefaultOverdueUserApi implements OverdueUserApi {
     @Override
     public <T extends Blockable> void setOverrideBillingStateForAccount(
             T overdueable, BillingState<T> state) {
-        throw new NotImplementedException();
+        throw new UnsupportedOperationException();
     }
 
     public void setOverdueConfig(OverdueConfig config) {

payment/pom.xml 2(+1 -1)

diff --git a/payment/pom.xml b/payment/pom.xml
index 9c63544..e22d42a 100644
--- a/payment/pom.xml
+++ b/payment/pom.xml
@@ -13,7 +13,7 @@
     <parent>
         <groupId>com.ning.billing</groupId>
         <artifactId>killbill</artifactId>
-        <version>0.1.12-SNAPSHOT</version>
+        <version>0.1.13-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <artifactId>killbill-payment</artifactId>
diff --git a/payment/src/main/java/com/ning/billing/payment/api/DefaultPaymentErrorEvent.java b/payment/src/main/java/com/ning/billing/payment/api/DefaultPaymentErrorEvent.java
index a51d63d..15e0d7b 100644
--- a/payment/src/main/java/com/ning/billing/payment/api/DefaultPaymentErrorEvent.java
+++ b/payment/src/main/java/com/ning/billing/payment/api/DefaultPaymentErrorEvent.java
@@ -17,16 +17,12 @@
 package com.ning.billing.payment.api;
 import java.util.UUID;
 
-import org.codehaus.jackson.annotate.JsonCreator;
-import org.codehaus.jackson.annotate.JsonIgnore;
-import org.codehaus.jackson.annotate.JsonProperty;
-import org.codehaus.jackson.annotate.JsonTypeInfo;
-import org.codehaus.jackson.annotate.JsonTypeInfo.Id;
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
 
-import com.ning.billing.util.bus.BusEvent;
-import com.ning.billing.util.bus.BusEvent.BusEventType;
-
-@JsonTypeInfo(use = Id.NAME, property = "error")
+@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "error")
 public class DefaultPaymentErrorEvent implements PaymentErrorEvent {
 	
     private final String type;
diff --git a/payment/src/main/java/com/ning/billing/payment/api/DefaultPaymentInfoEvent.java b/payment/src/main/java/com/ning/billing/payment/api/DefaultPaymentInfoEvent.java
index eb48f30..2bf6a59 100644
--- a/payment/src/main/java/com/ning/billing/payment/api/DefaultPaymentInfoEvent.java
+++ b/payment/src/main/java/com/ning/billing/payment/api/DefaultPaymentInfoEvent.java
@@ -19,22 +19,20 @@ package com.ning.billing.payment.api;
 import java.math.BigDecimal;
 import java.util.UUID;
 
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
 import com.ning.billing.util.entity.EntityBase;
-import org.codehaus.jackson.annotate.JsonCreator;
-import org.codehaus.jackson.annotate.JsonIgnore;
-import org.codehaus.jackson.annotate.JsonProperty;
 import org.joda.time.DateTime;
 
 import com.google.common.base.Objects;
 
 import com.ning.billing.payment.plugin.api.PaymentInfoPlugin;
-import com.ning.billing.util.bus.BusEvent;
-import com.ning.billing.util.bus.BusEvent.BusEventType;
 
 public class DefaultPaymentInfoEvent extends EntityBase implements PaymentInfoEvent {
-
     private final UUID accountId;
-    private final UUID invoiceId;    
+    private final UUID invoiceId;  
+    private final String externalPaymentId;
     private final BigDecimal amount;
     private final BigDecimal refundAmount;
     private final String paymentNumber;
@@ -55,6 +53,7 @@ public class DefaultPaymentInfoEvent extends EntityBase implements PaymentInfoEv
     public DefaultPaymentInfoEvent(@JsonProperty("id") UUID id,
             @JsonProperty("accountId") UUID accountId,
             @JsonProperty("invoiceId") UUID invoiceId,            
+            @JsonProperty("externalPaymentId") String externalPaymentId,
             @JsonProperty("amount") BigDecimal amount,
             @JsonProperty("refundAmount") BigDecimal refundAmount,
             @JsonProperty("bankIdentificationNumber") String bankIdentificationNumber,
@@ -73,6 +72,7 @@ public class DefaultPaymentInfoEvent extends EntityBase implements PaymentInfoEv
         super(id);
         this.accountId = accountId;
         this.invoiceId = invoiceId;
+        this.externalPaymentId = externalPaymentId;
         this.amount = amount;
         this.refundAmount = refundAmount;
         this.bankIdentificationNumber = bankIdentificationNumber;
@@ -94,6 +94,7 @@ public class DefaultPaymentInfoEvent extends EntityBase implements PaymentInfoEv
         this(src.id,
                 src.accountId,
                 src.invoiceId,
+                src.externalPaymentId,
                 src.amount,
                 src.refundAmount,
                 src.bankIdentificationNumber,
@@ -113,7 +114,7 @@ public class DefaultPaymentInfoEvent extends EntityBase implements PaymentInfoEv
     
 
     public DefaultPaymentInfoEvent(PaymentInfoPlugin info, UUID accountId, UUID invoiceId) {
-        this(UUID.randomUUID(), accountId,  invoiceId, info.getAmount(), info.getRefundAmount(), info.getBankIdentificationNumber(), info.getPaymentNumber(),
+        this(UUID.randomUUID(), accountId,  invoiceId, info.getExternalPaymentId(), info.getAmount(), info.getRefundAmount(), info.getBankIdentificationNumber(), info.getPaymentNumber(),
                 info.getStatus(), info.getCardType(), info.getReferenceId(), info.getPaymentMethodId(), info.getPaymentMethod(), info.getCardType(), info.getCardCountry(),
                 null, info.getEffectiveDate(), info.getCreatedDate(), info.getUpdatedDate());
     }
@@ -151,6 +152,11 @@ public class DefaultPaymentInfoEvent extends EntityBase implements PaymentInfoEv
     }
 
     @Override
+    public String getExternalPaymentId() {
+        return externalPaymentId;
+    }
+    
+    @Override
     public BigDecimal getAmount() {
         return amount;
     }
@@ -220,12 +226,11 @@ public class DefaultPaymentInfoEvent extends EntityBase implements PaymentInfoEv
         return updatedDate;
     }
 
-
     public static class Builder {
-
         private UUID id;
         private UUID accountId;
         private UUID invoiceId;
+        private String externalPaymentId;
         private BigDecimal amount;
         private BigDecimal refundAmount;
         private String paymentNumber;
@@ -249,6 +254,7 @@ public class DefaultPaymentInfoEvent extends EntityBase implements PaymentInfoEv
             this.id = src.id;
             this.accountId = src.accountId;
             this.invoiceId = src.invoiceId;
+            this.externalPaymentId = src.externalPaymentId;
             this.amount = src.amount;
             this.refundAmount = src.refundAmount;
             this.paymentNumber = src.paymentNumber;
@@ -283,6 +289,11 @@ public class DefaultPaymentInfoEvent extends EntityBase implements PaymentInfoEv
             return this;
         }
 
+        public Builder setExternalPaymentId(String externalPaymentId) {
+            this.externalPaymentId = externalPaymentId;
+            return this;
+        }
+
         public Builder setAmount(BigDecimal amount) {
             this.amount = amount;
             return this;
@@ -362,6 +373,7 @@ public class DefaultPaymentInfoEvent extends EntityBase implements PaymentInfoEv
             return new DefaultPaymentInfoEvent(id,
                     accountId,
                     invoiceId,
+                    externalPaymentId, 
                     amount,
                     refundAmount,
                     bankIdentificationNumber,
@@ -384,6 +396,7 @@ public class DefaultPaymentInfoEvent extends EntityBase implements PaymentInfoEv
     @Override
     public int hashCode() {
         return Objects.hashCode(id,
+                externalPaymentId, 
                 amount,
                 refundAmount,
                 bankIdentificationNumber,
@@ -405,6 +418,7 @@ public class DefaultPaymentInfoEvent extends EntityBase implements PaymentInfoEv
 
         final DefaultPaymentInfoEvent that = (DefaultPaymentInfoEvent) o;
 
+        if (!externalPaymentId.equals(that.externalPaymentId)) return false;
         if (amount != null ? !(amount.compareTo(that.amount) == 0) : that.amount != null) return false;
         if (bankIdentificationNumber != null ? !bankIdentificationNumber.equals(that.bankIdentificationNumber) : that.bankIdentificationNumber != null)
             return false;
diff --git a/payment/src/main/java/com/ning/billing/payment/dao/PaymentHistoryBinder.java b/payment/src/main/java/com/ning/billing/payment/dao/PaymentHistoryBinder.java
index 2ec9fc7..56f9026 100644
--- a/payment/src/main/java/com/ning/billing/payment/dao/PaymentHistoryBinder.java
+++ b/payment/src/main/java/com/ning/billing/payment/dao/PaymentHistoryBinder.java
@@ -45,18 +45,19 @@ public @interface PaymentHistoryBinder {
 
                     PaymentInfoEvent paymentInfo = history.getEntity();
                     q.bind("id", paymentInfo.getId().toString());
+                    q.bind("externalPaymentId", paymentInfo.getExternalPaymentId());
                     q.bind("amount", paymentInfo.getAmount());
-                    q.bind("refund_amount", paymentInfo.getRefundAmount());
-                    q.bind("payment_number", paymentInfo.getPaymentNumber());
-                    q.bind("bank_identification_number", paymentInfo.getBankIdentificationNumber());
+                    q.bind("refundAmount", paymentInfo.getRefundAmount());
+                    q.bind("paymentNumber", paymentInfo.getPaymentNumber());
+                    q.bind("bankIdentificationNumber", paymentInfo.getBankIdentificationNumber());
                     q.bind("status", paymentInfo.getStatus());
-                    q.bind("payment_type", paymentInfo.getType());
-                    q.bind("reference_id", paymentInfo.getReferenceId());
-                    q.bind("payment_method_id", paymentInfo.getPaymentMethodId());
-                    q.bind("payment_method", paymentInfo.getPaymentMethod());
-                    q.bind("card_type", paymentInfo.getCardType());
-                    q.bind("card_country", paymentInfo.getCardCountry());
-                    q.bind("effective_date", getDate(paymentInfo.getEffectiveDate()));
+                    q.bind("paymentType", paymentInfo.getType());
+                    q.bind("referenceId", paymentInfo.getReferenceId());
+                    q.bind("paymentMethodId", paymentInfo.getPaymentMethodId());
+                    q.bind("paymentMethod", paymentInfo.getPaymentMethod());
+                    q.bind("cardType", paymentInfo.getCardType());
+                    q.bind("cardCountry", paymentInfo.getCardCountry());
+                    q.bind("effectiveDate", getDate(paymentInfo.getEffectiveDate()));
                 }
             };
         }
diff --git a/payment/src/main/java/com/ning/billing/payment/dao/PaymentSqlDao.java b/payment/src/main/java/com/ning/billing/payment/dao/PaymentSqlDao.java
index 18ae0f4..7cda209 100644
--- a/payment/src/main/java/com/ning/billing/payment/dao/PaymentSqlDao.java
+++ b/payment/src/main/java/com/ning/billing/payment/dao/PaymentSqlDao.java
@@ -50,13 +50,13 @@ import com.ning.billing.payment.api.PaymentInfoEvent;
 @RegisterMapper(PaymentSqlDao.PaymentInfoMapper.class)
 public interface PaymentSqlDao extends Transactional<PaymentSqlDao>, UpdatableEntitySqlDao<PaymentInfoEvent>, CloseMe {
     @SqlQuery
-    PaymentInfoEvent getPaymentInfoForPaymentAttemptId(@Bind("payment_attempt_id") String paymentAttemptId);
+    PaymentInfoEvent getPaymentInfoForPaymentAttemptId(@Bind("paymentAttemptId") String paymentAttemptId);
 
     @SqlUpdate
-    void updatePaymentInfo(@Bind("payment_method") String paymentMethod,
+    void updatePaymentInfo(@Bind("paymentMethod") String paymentMethod,
                            @Bind("id") String paymentId,
-                           @Bind("card_type") String cardType,
-                           @Bind("card_country") String cardCountry,
+                           @Bind("cardType") String cardType,
+                           @Bind("cardCountry") String cardCountry,
                            @CallContextBinder CallContext context);
 
     @SqlQuery
@@ -82,18 +82,19 @@ public interface PaymentSqlDao extends Transactional<PaymentSqlDao>, UpdatableEn
         @Override
         public void bind(@SuppressWarnings("rawtypes") SQLStatement stmt, Bind bind, PaymentInfoEvent paymentInfo) {
             stmt.bind("id", paymentInfo.getId().toString());
+            stmt.bind("externalPaymentId", paymentInfo.getExternalPaymentId());
             stmt.bind("amount", paymentInfo.getAmount());
-            stmt.bind("refund_amount", paymentInfo.getRefundAmount());
-            stmt.bind("payment_number", paymentInfo.getPaymentNumber());
-            stmt.bind("bank_identification_number", paymentInfo.getBankIdentificationNumber());
+            stmt.bind("refundAmount", paymentInfo.getRefundAmount());
+            stmt.bind("paymentNumber", paymentInfo.getPaymentNumber());
+            stmt.bind("bankIdentificationNumber", paymentInfo.getBankIdentificationNumber());
             stmt.bind("status", paymentInfo.getStatus());
-            stmt.bind("payment_type", paymentInfo.getType());
-            stmt.bind("reference_id", paymentInfo.getReferenceId());
-            stmt.bind("payment_method_id", paymentInfo.getPaymentMethodId());
-            stmt.bind("payment_method", paymentInfo.getPaymentMethod());
-            stmt.bind("card_type", paymentInfo.getCardType());
-            stmt.bind("card_country", paymentInfo.getCardCountry());
-            stmt.bind("effective_date", getDate(paymentInfo.getEffectiveDate()));
+            stmt.bind("paymentType", paymentInfo.getType());
+            stmt.bind("referenceId", paymentInfo.getReferenceId());
+            stmt.bind("paymentMethodId", paymentInfo.getPaymentMethodId());
+            stmt.bind("paymentMethod", paymentInfo.getPaymentMethod());
+            stmt.bind("cardType", paymentInfo.getCardType());
+            stmt.bind("cardCountry", paymentInfo.getCardCountry());
+            stmt.bind("effectiveDate", getDate(paymentInfo.getEffectiveDate()));
         }
     }
 
@@ -104,6 +105,7 @@ public interface PaymentSqlDao extends Transactional<PaymentSqlDao>, UpdatableEn
             UUID accountId = getUUID(rs, "account_id");
             UUID invoiceId = getUUID(rs, "invoice_id");            
             UUID id = getUUID(rs, "id");
+            String externalPaymentId = rs.getString("external_payment_id");
             BigDecimal amount = rs.getBigDecimal("amount");
             BigDecimal refundAmount = rs.getBigDecimal("refund_amount");
             String paymentNumber = rs.getString("payment_number");
@@ -122,6 +124,7 @@ public interface PaymentSqlDao extends Transactional<PaymentSqlDao>, UpdatableEn
             return new DefaultPaymentInfoEvent(id,
                     accountId,
                     invoiceId,
+                    externalPaymentId,
                     amount,
                     refundAmount,
                     bankIdentificationNumber,
diff --git a/payment/src/main/java/com/ning/billing/payment/provider/NoOpPaymentProviderPlugin.java b/payment/src/main/java/com/ning/billing/payment/provider/NoOpPaymentProviderPlugin.java
index 296731f..f3f274a 100644
--- a/payment/src/main/java/com/ning/billing/payment/provider/NoOpPaymentProviderPlugin.java
+++ b/payment/src/main/java/com/ning/billing/payment/provider/NoOpPaymentProviderPlugin.java
@@ -99,6 +99,12 @@ public class NoOpPaymentProviderPlugin implements PaymentProviderPlugin {
             public String getBankIdentificationNumber() {
                 return null;
             }
+
+            @Override
+            public String getExternalPaymentId() {
+                return null;
+            }
+
             @Override
             public BigDecimal getAmount() {
                 return invoice.getBalance();
diff --git a/payment/src/main/resources/com/ning/billing/payment/dao/PaymentSqlDao.sql.stg b/payment/src/main/resources/com/ning/billing/payment/dao/PaymentSqlDao.sql.stg
index 04167f7..b608061 100644
--- a/payment/src/main/resources/com/ning/billing/payment/dao/PaymentSqlDao.sql.stg
+++ b/payment/src/main/resources/com/ning/billing/payment/dao/PaymentSqlDao.sql.stg
@@ -2,6 +2,7 @@ group PaymentSqlDao;
 
 paymentInfoFields(prefix) ::= <<
     <prefix>id,
+    <prefix>external_payment_id,
     <prefix>amount,
     <prefix>refund_amount,
     <prefix>bank_identification_number,
@@ -22,16 +23,16 @@ paymentInfoFields(prefix) ::= <<
 
 insertPaymentInfo() ::= <<
     INSERT INTO payments (<paymentInfoFields()>)
-    VALUES (:id, :amount, :refund_amount, :bank_identification_number, :payment_number,
-    :payment_type, :status, :reference_id, :payment_method_id, :payment_method, :card_type,
-    :card_country, :effective_date, :userName, :createdDate, :userName, :createdDate);
+    VALUES (:id, :externalPaymentId, :amount, :refundAmount, :bankIdentificationNumber, :paymentNumber,
+    :paymentType, :status, :referenceId, :paymentMethodId, :paymentMethod, :cardType,
+    :cardCountry, :effectiveDate, :userName, :createdDate, :userName, :createdDate);
 >>
 
 updatePaymentInfo() ::= <<
     UPDATE payments
-       SET payment_method = :payment_method,
-           card_type = :card_type,
-           card_country = :card_country,
+       SET payment_method = :paymentMethod,
+           card_type = :cardType,
+           card_country = :cardCountry,
            updated_by = :userName,
            updated_date = :updatedDate
      WHERE id = :id
@@ -62,7 +63,7 @@ getPaymentInfoForPaymentAttemptId() ::= <<
     , pa.account_id
     , pa.invoice_id
       FROM payments p, payment_attempts pa
-    WHERE pa.id = :payment_attempt_id
+    WHERE pa.id = :paymentAttemptId
        AND pa.payment_id = p.id
 >>
 
@@ -77,6 +78,7 @@ getPaymentInfo() ::= <<
 historyFields(prefix) ::= <<
     record_id,
     id,
+    external_payment_id,
     amount,
     refund_amount,
     payment_number,
@@ -97,9 +99,9 @@ historyFields(prefix) ::= <<
 
 insertHistoryFromTransaction() ::= <<
     INSERT INTO payment_history (<historyFields()>)
-    VALUES (:recordId, :id, :amount, :refund_amount, :bank_identification_number, :payment_number,
-    :payment_type, :status, :reference_id, :payment_method_id, :payment_method, :card_type,
-    :card_country, :effective_date, :userName, :createdDate, :userName, :updatedDate);
+    VALUES (:recordId, :id, :externalPaymentId, :amount, :refundAmount, :bankIdentificationNumber, :paymentNumber,
+    :paymentType, :status, :referenceId, :paymentMethodId, :paymentMethod, :cardType,
+    :cardCountry, :effectiveDate, :userName, :createdDate, :userName, :updatedDate);
 >>
 
 getRecordId() ::= <<
diff --git a/payment/src/main/resources/com/ning/billing/payment/ddl.sql b/payment/src/main/resources/com/ning/billing/payment/ddl.sql
index 7ef4570..5542abd 100644
--- a/payment/src/main/resources/com/ning/billing/payment/ddl.sql
+++ b/payment/src/main/resources/com/ning/billing/payment/ddl.sql
@@ -7,7 +7,7 @@ CREATE TABLE payment_attempts (
     amount decimal(8,2),
     currency char(3),
     payment_attempt_date datetime NOT NULL,
-    payment_id varchar(36) COLLATE utf8_bin,
+    payment_id char(36) COLLATE utf8_bin,
     retry_count tinyint,
     processing_status varchar(20),    
     invoice_date datetime NOT NULL,
@@ -30,7 +30,7 @@ CREATE TABLE payment_attempt_history (
     amount decimal(8,2),
     currency char(3),
     payment_attempt_date datetime NOT NULL,
-    payment_id varchar(36) COLLATE utf8_bin,
+    payment_id char(36) COLLATE utf8_bin,
     retry_count tinyint,
     processing_status varchar(20),        
     invoice_date datetime NOT NULL,
@@ -46,6 +46,7 @@ DROP TABLE IF EXISTS payments;
 CREATE TABLE payments (
     record_id int(11) unsigned NOT NULL AUTO_INCREMENT,
     id char(36) NOT NULL,
+    external_payment_id varchar(36) COLLATE utf8_bin NOT NULL,
     amount decimal(8,2),
     refund_amount decimal(8,2),
     payment_number varchar(36) COLLATE utf8_bin,
@@ -71,6 +72,7 @@ CREATE TABLE payment_history (
     history_record_id int(11) unsigned NOT NULL AUTO_INCREMENT,
     record_id int(11) unsigned NOT NULL,
     id char(36) NOT NULL,
+    external_payment_id varchar(36) COLLATE utf8_bin NOT NULL,
     amount decimal(8,2),
     refund_amount decimal(8,2),
     payment_number varchar(36) COLLATE utf8_bin,
diff --git a/payment/src/test/java/com/ning/billing/payment/api/TestEventJson.java b/payment/src/test/java/com/ning/billing/payment/api/TestEventJson.java
index 71356d6..a5a7fff 100644
--- a/payment/src/test/java/com/ning/billing/payment/api/TestEventJson.java
+++ b/payment/src/test/java/com/ning/billing/payment/api/TestEventJson.java
@@ -18,25 +18,14 @@ package com.ning.billing.payment.api;
 import java.math.BigDecimal;
 import java.util.UUID;
 
-import org.codehaus.jackson.map.ObjectMapper;
-import org.codehaus.jackson.map.SerializationConfig;
+import com.ning.billing.util.jackson.ObjectMapper;
 import org.joda.time.DateTime;
 import org.testng.Assert;
-import org.testng.annotations.BeforeTest;
 import org.testng.annotations.Test;
 
-
 public class TestEventJson {
-
-
     private ObjectMapper mapper = new ObjectMapper();
 
-    @BeforeTest(groups= {"fast"})
-    public void setup() {
-        mapper = new ObjectMapper();
-        mapper.disable(SerializationConfig.Feature.WRITE_DATES_AS_TIMESTAMPS);
-    }
-
     @Test(groups= {"fast"})
     public void testPaymentErrorEvent() throws Exception {
         PaymentErrorEvent e = new DefaultPaymentErrorEvent("credit card", "Failed payment", UUID.randomUUID(), UUID.randomUUID(), UUID.randomUUID());
@@ -49,7 +38,7 @@ public class TestEventJson {
     
     @Test(groups= {"fast"})
     public void testPaymentInfoEvent() throws Exception {
-        PaymentInfoEvent e = new DefaultPaymentInfoEvent(UUID.randomUUID(), UUID.randomUUID(), UUID.randomUUID(), new BigDecimal(12), new BigDecimal(12.9), "BNP", "eeert", "success",
+        PaymentInfoEvent e = new DefaultPaymentInfoEvent(UUID.randomUUID(), UUID.randomUUID(), UUID.randomUUID(), "932587sdkjgfh", new BigDecimal(12), new BigDecimal(12.9), "BNP", "eeert", "success",
                 "credit", "ref", "paypal", "paypal", "", "", UUID.randomUUID(), new DateTime(), new DateTime(), new DateTime());
         
         String json = mapper.writeValueAsString(e);
diff --git a/payment/src/test/java/com/ning/billing/payment/dao/TestPaymentDao.java b/payment/src/test/java/com/ning/billing/payment/dao/TestPaymentDao.java
index 9960ab7..fc56d95 100644
--- a/payment/src/test/java/com/ning/billing/payment/dao/TestPaymentDao.java
+++ b/payment/src/test/java/com/ning/billing/payment/dao/TestPaymentDao.java
@@ -47,6 +47,7 @@ public abstract class TestPaymentDao {
     @Test(groups={"slow"})
     public void testCreatePayment() {
         PaymentInfoEvent paymentInfo = new DefaultPaymentInfoEvent.Builder().setId(UUID.randomUUID())
+                .setExternalPaymentId("40863fe3f6dca54")
                 .setAmount(BigDecimal.TEN)
                 .setStatus("Processed")
                 .setBankIdentificationNumber("1234")
@@ -63,6 +64,7 @@ public abstract class TestPaymentDao {
     @Test(groups={"slow"})
     public void testUpdatePaymentInfo() {
         PaymentInfoEvent paymentInfo = new DefaultPaymentInfoEvent.Builder().setId(UUID.randomUUID())
+                .setExternalPaymentId("40863fe3f6dca54")
                 .setAmount(BigDecimal.TEN)
                 .setStatus("Processed")
                 .setBankIdentificationNumber("1234")
@@ -122,6 +124,7 @@ public abstract class TestPaymentDao {
         Assert.assertEquals(attempt3, attempt4);
 
         PaymentInfoEvent originalPaymentInfo = new DefaultPaymentInfoEvent.Builder().setId(paymentId)
+                .setExternalPaymentId("test test")
                 .setAmount(invoiceAmount)
                 .setStatus("Processed")
                 .setBankIdentificationNumber("1234")
diff --git a/payment/src/test/java/com/ning/billing/payment/MockInvoiceCreationEvent.java b/payment/src/test/java/com/ning/billing/payment/MockInvoiceCreationEvent.java
index 9a700cd..da9b6ab 100644
--- a/payment/src/test/java/com/ning/billing/payment/MockInvoiceCreationEvent.java
+++ b/payment/src/test/java/com/ning/billing/payment/MockInvoiceCreationEvent.java
@@ -19,14 +19,13 @@ package com.ning.billing.payment;
 import java.math.BigDecimal;
 import java.util.UUID;
 
-import org.codehaus.jackson.annotate.JsonCreator;
-import org.codehaus.jackson.annotate.JsonIgnore;
-import org.codehaus.jackson.annotate.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
 import org.joda.time.DateTime;
 
 import com.ning.billing.catalog.api.Currency;
 import com.ning.billing.invoice.api.InvoiceCreationEvent;
-import com.ning.billing.util.bus.BusEvent.BusEventType;
 
 public class MockInvoiceCreationEvent implements InvoiceCreationEvent {
 	
diff --git a/payment/src/test/java/com/ning/billing/payment/plugin/api/MockPaymentInfoPlugin.java b/payment/src/test/java/com/ning/billing/payment/plugin/api/MockPaymentInfoPlugin.java
index 8d4428e..b365665 100644
--- a/payment/src/test/java/com/ning/billing/payment/plugin/api/MockPaymentInfoPlugin.java
+++ b/payment/src/test/java/com/ning/billing/payment/plugin/api/MockPaymentInfoPlugin.java
@@ -23,7 +23,7 @@ import org.joda.time.DateTime;
 import com.ning.billing.payment.api.PaymentInfoEvent;
 
 public class MockPaymentInfoPlugin implements PaymentInfoPlugin {
-
+    private final String externalPaymentId;
     private final BigDecimal amount;
     private final String bankIdentificationNumber;
     private final DateTime createdDate;
@@ -42,6 +42,7 @@ public class MockPaymentInfoPlugin implements PaymentInfoPlugin {
     
     public MockPaymentInfoPlugin(PaymentInfoEvent info) {
         super();
+        this.externalPaymentId = info.getExternalPaymentId();
         this.amount = info.getAmount();
         this.bankIdentificationNumber = info.getBankIdentificationNumber();
         this.createdDate = info.getCreatedDate();
@@ -60,6 +61,11 @@ public class MockPaymentInfoPlugin implements PaymentInfoPlugin {
 
 
     @Override
+    public String getExternalPaymentId() {
+        return externalPaymentId;
+    }
+
+    @Override
     public BigDecimal getAmount() {
         return amount;
     }
diff --git a/payment/src/test/java/com/ning/billing/payment/provider/MockPaymentProviderPlugin.java b/payment/src/test/java/com/ning/billing/payment/provider/MockPaymentProviderPlugin.java
index e614c74..e9a1a9b 100644
--- a/payment/src/test/java/com/ning/billing/payment/provider/MockPaymentProviderPlugin.java
+++ b/payment/src/test/java/com/ning/billing/payment/provider/MockPaymentProviderPlugin.java
@@ -72,16 +72,17 @@ public class MockPaymentProviderPlugin implements PaymentProviderPlugin {
         }
 
         PaymentInfoEvent payment = new DefaultPaymentInfoEvent.Builder().setId(UUID.randomUUID())
-        .setAmount(invoice.getBalance())
-        .setStatus("Processed")
-        .setBankIdentificationNumber("1234")
-        .setCreatedDate(clock.getUTCNow())
-        .setEffectiveDate(clock.getUTCNow())
-        .setPaymentNumber("12345")
-        .setReferenceId("12345")
-        .setType("Electronic")
-        .setPaymentMethodId("123-456-678-89")
-        .build();
+                .setExternalPaymentId("238957t49regyuihfd")
+                .setAmount(invoice.getBalance())
+                .setStatus("Processed")
+                .setBankIdentificationNumber("1234")
+                .setCreatedDate(clock.getUTCNow())
+                .setEffectiveDate(clock.getUTCNow())
+                .setPaymentNumber("12345")
+                .setReferenceId("12345")
+                .setType("Electronic")
+                .setPaymentMethodId("123-456-678-89")
+                .build();
         
         return new MockPaymentInfoPlugin(payment);
     }

pom.xml 37(+21 -16)

diff --git a/pom.xml b/pom.xml
index 0972e2a..2801091 100644
--- a/pom.xml
+++ b/pom.xml
@@ -17,7 +17,7 @@
     <groupId>com.ning.billing</groupId>
     <artifactId>killbill</artifactId>
     <packaging>pom</packaging>
-    <version>0.1.12-SNAPSHOT</version>
+    <version>0.1.13-SNAPSHOT</version>
     <name>killbill</name>
     <description>Library for managing recurring subscriptions and the associated billing</description>
     <url>http://github.com/ning/killbill</url>
@@ -194,21 +194,6 @@
                 <scope>test</scope>
             </dependency>
             <dependency>
-                <groupId>org.codehaus.jackson</groupId>
-                <artifactId>jackson-core-asl</artifactId>
-                <version>1.9.5</version>
-            </dependency>
-            <dependency>
-                <groupId>org.codehaus.jackson</groupId>
-                <artifactId>jackson-jaxrs</artifactId>
-                <version>1.9.5</version>
-            </dependency>
-            <dependency>
-                <groupId>org.codehaus.jackson</groupId>
-                <artifactId>jackson-mapper-asl</artifactId>
-                <version>1.9.5</version>
-            </dependency>
-            <dependency>
                 <groupId>com.jolbox</groupId>
                 <artifactId>bonecp</artifactId>
                 <version>0.7.1.RELEASE</version>
@@ -220,6 +205,26 @@
                 </exclusions>
             </dependency>
             <dependency>
+                <groupId>com.fasterxml.jackson.core</groupId>
+                <artifactId>jackson-core</artifactId>
+                <version>2.0.0</version>
+            </dependency>
+            <dependency>
+                <groupId>com.fasterxml.jackson.core</groupId>
+                <artifactId>jackson-annotations</artifactId>
+                <version>2.0.0</version>
+            </dependency>
+            <dependency>
+                <groupId>com.fasterxml.jackson.datatype</groupId>
+                <artifactId>jackson-datatype-joda</artifactId>
+                <version>2.0.1</version>
+            </dependency>
+            <dependency>
+                <groupId>com.fasterxml.jackson.core</groupId>
+                <artifactId>jackson-databind</artifactId>
+                <version>2.0.0</version>
+            </dependency>
+            <dependency>
                 <groupId>com.google.guava</groupId>
                 <artifactId>guava</artifactId>
                 <version>10.0.1</version>

server/pom.xml 5(+2 -3)

diff --git a/server/pom.xml b/server/pom.xml
index 4d177de..0d19d77 100644
--- a/server/pom.xml
+++ b/server/pom.xml
@@ -8,13 +8,12 @@
 	OR CONDITIONS OF ANY KIND, either express or implied. See the ~ License for 
 	the specific language governing permissions and limitations ~ under the License. -->
 
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 	<modelVersion>4.0.0</modelVersion>
 	<parent>
 		<groupId>com.ning.billing</groupId>
 		<artifactId>killbill</artifactId>
-		<version>0.1.12-SNAPSHOT</version>
+		<version>0.1.13-SNAPSHOT</version>
 		<relativePath>../pom.xml</relativePath>
 	</parent>
 	<artifactId>killbill-server</artifactId>
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 414f2a0..94f2fb8 100644
--- a/server/src/test/java/com/ning/billing/jaxrs/TestAccount.java
+++ b/server/src/test/java/com/ning/billing/jaxrs/TestAccount.java
@@ -23,15 +23,14 @@ import java.util.HashMap;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
+import java.util.UUID;
 
 
 import javax.ws.rs.core.Response.Status;
 
 
-import org.codehaus.jackson.map.ObjectMapper;
-import org.codehaus.jackson.map.PropertyNamingStrategy;
+import com.ning.billing.jaxrs.resources.JaxrsResource;
 import org.joda.time.DateTime;
-import org.joda.time.Interval;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.testng.Assert;
@@ -42,20 +41,15 @@ import com.ning.billing.catalog.api.BillingPeriod;
 import com.ning.billing.catalog.api.ProductCategory;
 import com.ning.billing.jaxrs.json.AccountJson;
 import com.ning.billing.jaxrs.json.AccountTimelineJson;
-import com.ning.billing.jaxrs.json.BundleJsonNoSubsciptions;
+import com.ning.billing.jaxrs.json.BundleJsonNoSubscriptions;
 import com.ning.billing.jaxrs.json.CustomFieldJson;
 import com.ning.billing.jaxrs.json.SubscriptionJsonNoEvents;
 import com.ning.billing.jaxrs.json.TagDefinitionJson;
-import com.ning.billing.jaxrs.resources.BaseJaxrsResource;
 import com.ning.http.client.Response;
 
 
 public class TestAccount extends TestJaxrsBase {
-
 	private static final Logger log = LoggerFactory.getLogger(TestAccount.class);
-
-
-	
 	
 	@Test(groups="slow", enabled=true)
 	public void testAccountOk() throws Exception {
@@ -64,8 +58,8 @@ public class TestAccount extends TestJaxrsBase {
 		
 		// Retrieves by external key
 		Map<String, String> queryParams = new HashMap<String, String>();
-		queryParams.put(BaseJaxrsResource.QUERY_EXTERNAL_KEY, "shdgfhwe");
-		Response response = doGet(BaseJaxrsResource.ACCOUNTS_PATH, queryParams, DEFAULT_HTTP_TIMEOUT_SEC);
+		queryParams.put(JaxrsResource.QUERY_EXTERNAL_KEY, "shdgfhwe");
+		Response response = doGet(JaxrsResource.ACCOUNTS_PATH, queryParams, DEFAULT_HTTP_TIMEOUT_SEC);
 		Assert.assertEquals(response.getStatusCode(), Status.OK.getStatusCode());
 		String baseJson = response.getResponseBody();
 		AccountJson objFromJson = mapper.readValue(baseJson, AccountJson.class);
@@ -75,7 +69,7 @@ public class TestAccount extends TestJaxrsBase {
 		AccountJson newInput = new AccountJson(objFromJson.getAccountId(),
 				"zozo", 4, objFromJson.getExternalKey(), "rr@google.com", 18, "EUR", "none", "UTC", "bl1", "bh2", "", "ca", "usa", "415-255-2991");
 		baseJson = mapper.writeValueAsString(newInput);
-		final String uri = BaseJaxrsResource.ACCOUNTS_PATH + "/" + objFromJson.getAccountId();
+		final String uri = JaxrsResource.ACCOUNTS_PATH + "/" + objFromJson.getAccountId();
 		response = doPut(uri, baseJson, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
 		Assert.assertEquals(response.getStatusCode(), Status.OK.getStatusCode());
 		baseJson = response.getResponseBody();
@@ -88,7 +82,7 @@ public class TestAccount extends TestJaxrsBase {
 	public void testUpdateNonExistentAccount() throws Exception {
 		AccountJson input = getAccountJson("xoxo", "shghaahwe", "xoxo@yahoo.com");
 		String baseJson = mapper.writeValueAsString(input);
-		final String uri = BaseJaxrsResource.ACCOUNTS_PATH + "/" + input.getAccountId();
+		final String uri = JaxrsResource.ACCOUNTS_PATH + "/" + input.getAccountId();
 		Response response = doPut(uri, baseJson, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
 		Assert.assertEquals(response.getStatusCode(), Status.NO_CONTENT.getStatusCode());
 		String body = response.getResponseBody();
@@ -98,14 +92,14 @@ public class TestAccount extends TestJaxrsBase {
 	
 	@Test(groups="slow", enabled=true)
 	public void testAccountNonExistent() throws Exception {
-		final String uri = BaseJaxrsResource.ACCOUNTS_PATH + "/99999999-b103-42f3-8b6e-dd244f1d0747";
+		final String uri = JaxrsResource.ACCOUNTS_PATH + "/99999999-b103-42f3-8b6e-dd244f1d0747";
 		Response response = doGet(uri, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
 		Assert.assertEquals(response.getStatusCode(), Status.NO_CONTENT.getStatusCode());
 	}
 	
 	@Test(groups="slow", enabled=true)
 	public void testAccountBadAccountId() throws Exception {
-		final String uri = BaseJaxrsResource.ACCOUNTS_PATH + "/yo";
+		final String uri = JaxrsResource.ACCOUNTS_PATH + "/yo";
 		Response response = doGet(uri, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
 		Assert.assertEquals(response.getStatusCode(), Status.NOT_FOUND.getStatusCode());
 	}
@@ -119,7 +113,7 @@ public class TestAccount extends TestJaxrsBase {
 	    AccountJson accountJson = createAccount("poney", "shdddqgfhwe", "poney@yahoo.com");
 	    assertNotNull(accountJson);
 	    
-	    BundleJsonNoSubsciptions bundleJson = createBundle(accountJson.getAccountId(), "996599");
+	    BundleJsonNoSubscriptions bundleJson = createBundle(accountJson.getAccountId(), "996599");
 	    assertNotNull(bundleJson);
 	    
         SubscriptionJsonNoEvents subscriptionJson = createSubscription(bundleJson.getBundleId(), "Shotgun", ProductCategory.BASE.toString(), BillingPeriod.MONTHLY.toString(), true);
@@ -131,7 +125,7 @@ public class TestAccount extends TestJaxrsBase {
         crappyWaitForLackOfProperSynchonization();
         
         
-        final String uri = BaseJaxrsResource.ACCOUNTS_PATH + "/" + accountJson.getAccountId() + "/" + BaseJaxrsResource.TIMELINE;
+        final String uri = JaxrsResource.ACCOUNTS_PATH + "/" + accountJson.getAccountId() + "/" + JaxrsResource.TIMELINE;
         
         Response response = doGet(uri, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
         Assert.assertEquals(response.getStatusCode(), Status.OK.getStatusCode());
@@ -147,58 +141,56 @@ public class TestAccount extends TestJaxrsBase {
         Assert.assertEquals(objFromJson.getBundles().get(0).getSubscriptions().get(0).getEvents().size(), 2);        
  	}
 
-	@Test(groups="slow", enabled=false)
-	public void testAccountWithTags() throws Exception {
+
+
+
+
+    protected String getRootPath() {
+        return JaxrsResource.ACCOUNTS_PATH;
+    }
+
+	@Test(groups="slow", enabled=true)
+	public void testTags() throws Exception {
 	    //Create Tag definition
 	    TagDefinitionJson input = new TagDefinitionJson("yoyo", "nothing more to say");
 	    String baseJson = mapper.writeValueAsString(input);
-	    Response response = doPost(BaseJaxrsResource.TAG_DEFINITIONS_PATH, baseJson, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
+	    Response response = doPost(JaxrsResource.TAG_DEFINITIONS_PATH, baseJson, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
 	    assertEquals(response.getStatusCode(), Status.CREATED.getStatusCode());
-	    
-	    AccountJson accountJson = createAccount("couroucoucou", "shdwdsqgfhwe", "couroucoucou@yahoo.com");
-	    assertNotNull(accountJson);
 	        
 	    Map<String, String> queryParams = new HashMap<String, String>();
-        queryParams.put(BaseJaxrsResource.QUERY_TAGS, input.getName());
-        String uri = BaseJaxrsResource.ACCOUNTS_PATH + "/" + BaseJaxrsResource.TAGS + "/" + accountJson.getAccountId() ;
+        queryParams.put(JaxrsResource.QUERY_TAGS, input.getName());
+        String uri = getRootPath() + "/" + JaxrsResource.TAGS + "/" + UUID.randomUUID().toString();
 	    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
-         * 
-        String location = response.getHeader("Location");
-        Assert.assertNotNull(location);
+         */
 
         // Retrieves by Id based on Location returned
-        response = doGetWithUrl(location, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
+        String url = getUrlFromUri(uri);
+        response = doGetWithUrl(url, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
         Assert.assertEquals(response.getStatusCode(), Status.OK.getStatusCode());
-        */
+
 
 	}
-	
-    @Test(groups="slow", enabled=false)
-	public void testAccountWithCustomFields() throws Exception {
-        
-        AccountJson accountJson = createAccount("carafe", "shdwhwgaz", "carafe@yahoo.com");
-        assertNotNull(accountJson);
-        
+
+    @Test(groups="slow", enabled=true)
+	public void testCustomFields() throws Exception {
         List<CustomFieldJson> customFields =  new LinkedList<CustomFieldJson>();
         customFields.add(new CustomFieldJson("1", "value1"));
         customFields.add(new CustomFieldJson("2", "value2"));
         customFields.add(new CustomFieldJson("3", "value3"));  
         String baseJson = mapper.writeValueAsString(customFields);
 
-        String uri = BaseJaxrsResource.ACCOUNTS_PATH + "/" + BaseJaxrsResource.CUSTOM_FIELDS + "/" + accountJson.getAccountId() ;
-        Response response = doPost(uri,baseJson, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
+        String uri = getRootPath() + "/" + JaxrsResource.CUSTOM_FIELDS + "/" + UUID.randomUUID().toString();
+        Response response = doPost(uri, baseJson, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
         assertEquals(response.getStatusCode(), Status.CREATED.getStatusCode());
-        String location = response.getHeader("Location");
-        Assert.assertNotNull(location);
 
         // Retrieves by Id based on Location returned
-        response = doGetWithUrl(location, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
+        String url = getUrlFromUri(uri);
+        response = doGetWithUrl(url, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
         Assert.assertEquals(response.getStatusCode(), Status.OK.getStatusCode());
-        
 	}
 }
diff --git a/server/src/test/java/com/ning/billing/jaxrs/TestBundle.java b/server/src/test/java/com/ning/billing/jaxrs/TestBundle.java
index 7795d0c..b15c8ea 100644
--- a/server/src/test/java/com/ning/billing/jaxrs/TestBundle.java
+++ b/server/src/test/java/com/ning/billing/jaxrs/TestBundle.java
@@ -30,8 +30,8 @@ import org.testng.annotations.Test;
 
 import com.fasterxml.jackson.core.type.TypeReference;
 import com.ning.billing.jaxrs.json.AccountJson;
-import com.ning.billing.jaxrs.json.BundleJsonNoSubsciptions;
-import com.ning.billing.jaxrs.resources.BaseJaxrsResource;
+import com.ning.billing.jaxrs.json.BundleJsonNoSubscriptions;
+import com.ning.billing.jaxrs.resources.JaxrsResource;
 import com.ning.http.client.Response;
 
 public class TestBundle extends TestJaxrsBase {
@@ -44,15 +44,15 @@ public class TestBundle extends TestJaxrsBase {
 	public void testBundleOk() throws Exception {
 
 		AccountJson accountJson = createAccount("xlxl", "shdgfhkkl", "xlxl@yahoo.com");
-		BundleJsonNoSubsciptions bundleJson = createBundle(accountJson.getAccountId(), "12345");
+		BundleJsonNoSubscriptions bundleJson = createBundle(accountJson.getAccountId(), "12345");
 		
 		// Retrieves by external key
 		Map<String, String> queryParams = new HashMap<String, String>();
-		queryParams.put(BaseJaxrsResource.QUERY_EXTERNAL_KEY, "12345");
-		Response response = doGet(BaseJaxrsResource.BUNDLES_PATH, queryParams, DEFAULT_HTTP_TIMEOUT_SEC);
+		queryParams.put(JaxrsResource.QUERY_EXTERNAL_KEY, "12345");
+		Response response = doGet(JaxrsResource.BUNDLES_PATH, queryParams, DEFAULT_HTTP_TIMEOUT_SEC);
 		Assert.assertEquals(response.getStatusCode(), Status.OK.getStatusCode());
 		String baseJson = response.getResponseBody();
-		BundleJsonNoSubsciptions objFromJson = mapper.readValue(baseJson, BundleJsonNoSubsciptions.class);
+		BundleJsonNoSubscriptions objFromJson = mapper.readValue(baseJson, BundleJsonNoSubscriptions.class);
 		Assert.assertTrue(objFromJson.equals(bundleJson));
 	}
 	
@@ -61,18 +61,18 @@ public class TestBundle extends TestJaxrsBase {
 	public void testBundleFromAccount() throws Exception {
 
 		AccountJson accountJson = createAccount("xaxa", "saagfhkkl", "xaxa@yahoo.com");
-		BundleJsonNoSubsciptions bundleJson1 = createBundle(accountJson.getAccountId(), "156567");
-		BundleJsonNoSubsciptions bundleJson2 = createBundle(accountJson.getAccountId(), "265658");
+		BundleJsonNoSubscriptions bundleJson1 = createBundle(accountJson.getAccountId(), "156567");
+		BundleJsonNoSubscriptions bundleJson2 = createBundle(accountJson.getAccountId(), "265658");
 
-		String uri = BaseJaxrsResource.ACCOUNTS_PATH + "/" + accountJson.getAccountId().toString() + "/" + BaseJaxrsResource.BUNDLES;
+		String uri = JaxrsResource.ACCOUNTS_PATH + "/" + accountJson.getAccountId().toString() + "/" + JaxrsResource.BUNDLES;
 		Response response = doGet(uri, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
 		Assert.assertEquals(response.getStatusCode(), Status.OK.getStatusCode());
 		String baseJson = response.getResponseBody();
-		List<BundleJsonNoSubsciptions> objFromJson = mapper.readValue(baseJson, new TypeReference<List<BundleJsonNoSubsciptions>>() {});
+		List<BundleJsonNoSubscriptions> objFromJson = mapper.readValue(baseJson, new TypeReference<List<BundleJsonNoSubscriptions>>() {});
 		
-		Collections.sort(objFromJson, new Comparator<BundleJsonNoSubsciptions>() {
+		Collections.sort(objFromJson, new Comparator<BundleJsonNoSubscriptions>() {
 			@Override
-			public int compare(BundleJsonNoSubsciptions o1, BundleJsonNoSubsciptions o2) {
+			public int compare(BundleJsonNoSubscriptions o1, BundleJsonNoSubscriptions o2) {
 				return o1.getExternalKey().compareTo(o2.getExternalKey());
 			}
 		});
@@ -84,30 +84,30 @@ public class TestBundle extends TestJaxrsBase {
 	public void testBundleNonExistent() throws Exception {
 		AccountJson accountJson = createAccount("dfdf", "dfdfgfhkkl", "dfdf@yahoo.com");	
 		
-		String uri = BaseJaxrsResource.BUNDLES_PATH + "/99999999-b103-42f3-8b6e-dd244f1d0747";
+		String uri = JaxrsResource.BUNDLES_PATH + "/99999999-b103-42f3-8b6e-dd244f1d0747";
 		Response response = doGet(uri, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
 		Assert.assertEquals(response.getStatusCode(), Status.NO_CONTENT.getStatusCode());
 		
 		
 		// Retrieves by external key
 		Map<String, String> queryParams = new HashMap<String, String>();
-		queryParams.put(BaseJaxrsResource.QUERY_EXTERNAL_KEY, "56566");
-		response = doGet(BaseJaxrsResource.BUNDLES_PATH, queryParams, DEFAULT_HTTP_TIMEOUT_SEC);
+		queryParams.put(JaxrsResource.QUERY_EXTERNAL_KEY, "56566");
+		response = doGet(JaxrsResource.BUNDLES_PATH, queryParams, DEFAULT_HTTP_TIMEOUT_SEC);
 		Assert.assertEquals(response.getStatusCode(), Status.NO_CONTENT.getStatusCode());
 		
 		
-		uri = BaseJaxrsResource.ACCOUNTS_PATH + "/" + accountJson.getAccountId().toString() + "/" + BaseJaxrsResource.BUNDLES;
+		uri = JaxrsResource.ACCOUNTS_PATH + "/" + accountJson.getAccountId().toString() + "/" + JaxrsResource.BUNDLES;
 		response = doGet(uri, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
 		Assert.assertEquals(response.getStatusCode(), Status.OK.getStatusCode());
 		String baseJson = response.getResponseBody();
-		List<BundleJsonNoSubsciptions> objFromJson = mapper.readValue(baseJson, new TypeReference<List<BundleJsonNoSubsciptions>>() {});
+		List<BundleJsonNoSubscriptions> objFromJson = mapper.readValue(baseJson, new TypeReference<List<BundleJsonNoSubscriptions>>() {});
 		Assert.assertNotNull(objFromJson);
 		Assert.assertEquals(objFromJson.size(), 0);
 	}
 
 	@Test(groups="slow", enabled=true)
 	public void testAppNonExistent() throws Exception {
-		String uri = BaseJaxrsResource.ACCOUNTS_PATH + "/99999999-b103-42f3-8b6e-dd244f1d0747/" + BaseJaxrsResource.BUNDLES;
+		String uri = JaxrsResource.ACCOUNTS_PATH + "/99999999-b103-42f3-8b6e-dd244f1d0747/" + JaxrsResource.BUNDLES;
 		Response response = doGet(uri, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
 		Assert.assertEquals(response.getStatusCode(), Status.NO_CONTENT.getStatusCode());	
 	}
diff --git a/server/src/test/java/com/ning/billing/jaxrs/TestInvoice.java b/server/src/test/java/com/ning/billing/jaxrs/TestInvoice.java
index aba67b8..6c0878b 100644
--- a/server/src/test/java/com/ning/billing/jaxrs/TestInvoice.java
+++ b/server/src/test/java/com/ning/billing/jaxrs/TestInvoice.java
@@ -24,6 +24,7 @@ import java.util.Map;
 
 import javax.ws.rs.core.Response.Status;
 
+import com.ning.billing.jaxrs.resources.JaxrsResource;
 import org.joda.time.DateTime;
 import org.joda.time.Interval;
 import org.joda.time.format.DateTimeFormatter;
@@ -37,10 +38,9 @@ import com.fasterxml.jackson.core.type.TypeReference;
 import com.ning.billing.catalog.api.BillingPeriod;
 import com.ning.billing.catalog.api.ProductCategory;
 import com.ning.billing.jaxrs.json.AccountJson;
-import com.ning.billing.jaxrs.json.BundleJsonNoSubsciptions;
+import com.ning.billing.jaxrs.json.BundleJsonNoSubscriptions;
 import com.ning.billing.jaxrs.json.InvoiceJsonSimple;
 import com.ning.billing.jaxrs.json.SubscriptionJsonNoEvents;
-import com.ning.billing.jaxrs.resources.BaseJaxrsResource;
 import com.ning.http.client.Response;
 
 public class TestInvoice extends TestJaxrsBase  {
@@ -60,7 +60,7 @@ public class TestInvoice extends TestJaxrsBase  {
         AccountJson accountJson = createAccount("poupou", "qhddffrwe", "poupou@yahoo.com");
         assertNotNull(accountJson);
         
-        BundleJsonNoSubsciptions bundleJson = createBundle(accountJson.getAccountId(), "9967599");
+        BundleJsonNoSubscriptions bundleJson = createBundle(accountJson.getAccountId(), "9967599");
         assertNotNull(bundleJson);
         
         SubscriptionJsonNoEvents subscriptionJson = createSubscription(bundleJson.getBundleId(), "Shotgun", ProductCategory.BASE.toString(), BillingPeriod.MONTHLY.toString(), true);
@@ -72,9 +72,9 @@ public class TestInvoice extends TestJaxrsBase  {
 
         crappyWaitForLackOfProperSynchonization();
         
-        String uri = BaseJaxrsResource.INVOICES_PATH;
+        String uri = JaxrsResource.INVOICES_PATH;
         Map<String, String> queryParams = new HashMap<String, String>();
-        queryParams.put(BaseJaxrsResource.QUERY_ACCOUNT_ID, accountJson.getAccountId());
+        queryParams.put(JaxrsResource.QUERY_ACCOUNT_ID, accountJson.getAccountId());
         
         Response response = doGet(uri, queryParams, DEFAULT_HTTP_TIMEOUT_SEC);
         Assert.assertEquals(response.getStatusCode(), Status.OK.getStatusCode());
@@ -85,7 +85,7 @@ public class TestInvoice extends TestJaxrsBase  {
         assertEquals(objFromJson.size(), 4);
         
         // Check we can retrieve an individual invoice
-        uri = BaseJaxrsResource.INVOICES_PATH + "/" + objFromJson.get(0).getInvoiceId();
+        uri = JaxrsResource.INVOICES_PATH + "/" + objFromJson.get(0).getInvoiceId();
         response = doGet(uri, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
         Assert.assertEquals(response.getStatusCode(), Status.OK.getStatusCode());        
         baseJson = response.getResponseBody();
@@ -95,9 +95,9 @@ public class TestInvoice extends TestJaxrsBase  {
         
         // Then create a dryRun Invoice
         DateTime futureDate = clock.getUTCNow().plusMonths(1).plusDays(3);
-        uri = BaseJaxrsResource.INVOICES_PATH;
-        queryParams.put(BaseJaxrsResource.QUERY_TARGET_DATE, futureDate.toString());
-        queryParams.put(BaseJaxrsResource.QUERY_DRY_RUN, "true");        
+        uri = JaxrsResource.INVOICES_PATH;
+        queryParams.put(JaxrsResource.QUERY_TARGET_DATE, futureDate.toString());
+        queryParams.put(JaxrsResource.QUERY_DRY_RUN, "true");
         response = doPost(uri, null, queryParams, DEFAULT_HTTP_TIMEOUT_SEC);
         Assert.assertEquals(response.getStatusCode(), Status.OK.getStatusCode()); 
         baseJson = response.getResponseBody();
@@ -106,7 +106,7 @@ public class TestInvoice extends TestJaxrsBase  {
         log.info(baseJson);
         
         // The one more time with no DryRun
-        queryParams.remove(BaseJaxrsResource.QUERY_DRY_RUN);
+        queryParams.remove(JaxrsResource.QUERY_DRY_RUN);
         response = doPost(uri, null, queryParams, DEFAULT_HTTP_TIMEOUT_SEC);
         Assert.assertEquals(response.getStatusCode(), Status.CREATED.getStatusCode());
         
@@ -114,7 +114,7 @@ public class TestInvoice extends TestJaxrsBase  {
         Assert.assertNotNull(location);
         
         // Check again # invoices, should be 5 this time
-        uri = BaseJaxrsResource.INVOICES_PATH;
+        uri = JaxrsResource.INVOICES_PATH;
         response = doGet(uri, queryParams, DEFAULT_HTTP_TIMEOUT_SEC);
         assertEquals(response.getStatusCode(), Status.OK.getStatusCode());
         baseJson = response.getResponseBody();
diff --git a/server/src/test/java/com/ning/billing/jaxrs/TestJaxrsBase.java b/server/src/test/java/com/ning/billing/jaxrs/TestJaxrsBase.java
index 46214e9..a09bf1a 100644
--- a/server/src/test/java/com/ning/billing/jaxrs/TestJaxrsBase.java
+++ b/server/src/test/java/com/ning/billing/jaxrs/TestJaxrsBase.java
@@ -30,6 +30,7 @@ import java.util.concurrent.TimeUnit;
 
 import javax.ws.rs.core.Response.Status;
 
+import com.ning.billing.jaxrs.resources.JaxrsResource;
 import com.ning.billing.util.email.EmailModule;
 import com.ning.billing.util.email.templates.TemplateModule;
 import com.ning.billing.util.glue.GlobalLockerModule;
@@ -63,9 +64,8 @@ import com.ning.billing.dbi.MysqlTestingHelper;
 import com.ning.billing.entitlement.glue.DefaultEntitlementModule;
 import com.ning.billing.invoice.glue.DefaultInvoiceModule;
 import com.ning.billing.jaxrs.json.AccountJson;
-import com.ning.billing.jaxrs.json.BundleJsonNoSubsciptions;
+import com.ning.billing.jaxrs.json.BundleJsonNoSubscriptions;
 import com.ning.billing.jaxrs.json.SubscriptionJsonNoEvents;
-import com.ning.billing.jaxrs.resources.BaseJaxrsResource;
 import com.ning.billing.junction.glue.DefaultJunctionModule;
 import com.ning.billing.payment.provider.MockPaymentProviderPluginModule;
 import com.ning.billing.payment.setup.PaymentModule;
@@ -311,7 +311,7 @@ public class TestJaxrsBase {
     protected AccountJson createAccount(String name, String key, String email) throws Exception {
         AccountJson input = getAccountJson(name, key, email);
         String baseJson = mapper.writeValueAsString(input);
-        Response response = doPost(BaseJaxrsResource.ACCOUNTS_PATH, baseJson, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
+        Response response = doPost(JaxrsResource.ACCOUNTS_PATH, baseJson, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
         Assert.assertEquals(response.getStatusCode(), Status.CREATED.getStatusCode());
 
         String location = response.getHeader("Location");
@@ -329,10 +329,10 @@ public class TestJaxrsBase {
 
 
 
-    protected BundleJsonNoSubsciptions createBundle(String accountId, String key) throws Exception {
-        BundleJsonNoSubsciptions input = new BundleJsonNoSubsciptions(null, accountId, key, null);
+    protected BundleJsonNoSubscriptions createBundle(String accountId, String key) throws Exception {
+        BundleJsonNoSubscriptions input = new BundleJsonNoSubscriptions(null, accountId, key, null);
         String baseJson = mapper.writeValueAsString(input);
-        Response response = doPost(BaseJaxrsResource.BUNDLES_PATH, baseJson, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
+        Response response = doPost(JaxrsResource.BUNDLES_PATH, baseJson, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
         Assert.assertEquals(response.getStatusCode(), Status.CREATED.getStatusCode());
 
         String location = response.getHeader("Location");
@@ -343,7 +343,7 @@ public class TestJaxrsBase {
         Assert.assertEquals(response.getStatusCode(), Status.OK.getStatusCode());
 
         baseJson = response.getResponseBody();
-        BundleJsonNoSubsciptions objFromJson = mapper.readValue(baseJson, BundleJsonNoSubsciptions.class);
+        BundleJsonNoSubscriptions objFromJson = mapper.readValue(baseJson, BundleJsonNoSubscriptions.class);
         Assert.assertTrue(objFromJson.equalsNoId(input));
         return objFromJson;
     }
@@ -355,7 +355,7 @@ public class TestJaxrsBase {
 
 
         Map<String, String> queryParams = waitCompletion ? getQueryParamsForCallCompletion("5") : DEFAULT_EMPTY_QUERY;
-        Response response = doPost(BaseJaxrsResource.SUBSCRIPTIONS_PATH, baseJson, queryParams, DEFAULT_HTTP_TIMEOUT_SEC);
+        Response response = doPost(JaxrsResource.SUBSCRIPTIONS_PATH, baseJson, queryParams, DEFAULT_HTTP_TIMEOUT_SEC);
         Assert.assertEquals(response.getStatusCode(), Status.CREATED.getStatusCode());
 
         String location = response.getHeader("Location");
@@ -374,8 +374,8 @@ public class TestJaxrsBase {
 
     protected Map<String, String> getQueryParamsForCallCompletion(final String timeoutSec) {
         Map<String, String> queryParams = new HashMap<String, String>();
-        queryParams.put(BaseJaxrsResource.QUERY_CALL_COMPLETION, "true");
-        queryParams.put(BaseJaxrsResource.QUERY_CALL_TIMEOUT, timeoutSec);
+        queryParams.put(JaxrsResource.QUERY_CALL_COMPLETION, "true");
+        queryParams.put(JaxrsResource.QUERY_CALL_TIMEOUT, timeoutSec);
         return queryParams;
     }
 
@@ -422,9 +422,9 @@ public class TestJaxrsBase {
     private Response executeAndWait(final BoundRequestBuilder builder, final int timeoutSec, final boolean addContextHeader) {
         
         if (addContextHeader) {
-            builder.addHeader(BaseJaxrsResource.HDR_CREATED_BY, createdBy);
-            builder.addHeader(BaseJaxrsResource.HDR_REASON, reason);
-            builder.addHeader(BaseJaxrsResource.HDR_COMMENT, comment);            
+            builder.addHeader(JaxrsResource.HDR_CREATED_BY, createdBy);
+            builder.addHeader(JaxrsResource.HDR_REASON, reason);
+            builder.addHeader(JaxrsResource.HDR_COMMENT, comment);
         }
         
         Response response = null;
@@ -444,7 +444,7 @@ public class TestJaxrsBase {
         return response;
     }
 
-    private String getUrlFromUri(final String uri) {
+    protected String getUrlFromUri(final String uri) {
         return String.format("http://%s:%d%s", config.getServerHost(), config.getServerPort(), uri);
     }
 
diff --git a/server/src/test/java/com/ning/billing/jaxrs/TestSubscription.java b/server/src/test/java/com/ning/billing/jaxrs/TestSubscription.java
index d43c858..962352b 100644
--- a/server/src/test/java/com/ning/billing/jaxrs/TestSubscription.java
+++ b/server/src/test/java/com/ning/billing/jaxrs/TestSubscription.java
@@ -23,6 +23,7 @@ import java.util.UUID;
 
 import javax.ws.rs.core.Response.Status;
 
+import com.ning.billing.jaxrs.resources.JaxrsResource;
 import org.joda.time.DateTime;
 import org.joda.time.Interval;
 import org.slf4j.Logger;
@@ -34,9 +35,8 @@ import com.ning.billing.catalog.api.BillingPeriod;
 import com.ning.billing.catalog.api.PriceListSet;
 import com.ning.billing.catalog.api.ProductCategory;
 import com.ning.billing.jaxrs.json.AccountJson;
-import com.ning.billing.jaxrs.json.BundleJsonNoSubsciptions;
+import com.ning.billing.jaxrs.json.BundleJsonNoSubscriptions;
 import com.ning.billing.jaxrs.json.SubscriptionJsonNoEvents;
-import com.ning.billing.jaxrs.resources.BaseJaxrsResource;
 import com.ning.http.client.Response;
 
 public class TestSubscription extends TestJaxrsBase {
@@ -53,7 +53,7 @@ public class TestSubscription extends TestJaxrsBase {
         clock.setDeltaFromReality(initialDate.getMillis() - clock.getUTCNow().getMillis());
         
         AccountJson accountJson = createAccount("xil", "shdxilhkkl", "xil@yahoo.com");
-        BundleJsonNoSubsciptions bundleJson = createBundle(accountJson.getAccountId(), "99999");
+        BundleJsonNoSubscriptions bundleJson = createBundle(accountJson.getAccountId(), "99999");
 
         String productName = "Shotgun";
         BillingPeriod term = BillingPeriod.MONTHLY;
@@ -62,7 +62,7 @@ public class TestSubscription extends TestJaxrsBase {
         Assert.assertNotNull(subscriptionJson.getChargedThroughDate());
         Assert.assertEquals(subscriptionJson.getChargedThroughDate(), subscriptionJson.getStartDate().plusDays(30));        
         
-        String uri = BaseJaxrsResource.SUBSCRIPTIONS_PATH + "/" + subscriptionJson.getSubscriptionId().toString();
+        String uri = JaxrsResource.SUBSCRIPTIONS_PATH + "/" + subscriptionJson.getSubscriptionId().toString();
  
         
         // Retrieves with GET
@@ -99,19 +99,19 @@ public class TestSubscription extends TestJaxrsBase {
 
         //      
         // Cancel EOT
-        uri = BaseJaxrsResource.SUBSCRIPTIONS_PATH + "/" + subscriptionJson.getSubscriptionId().toString();
+        uri = JaxrsResource.SUBSCRIPTIONS_PATH + "/" + subscriptionJson.getSubscriptionId().toString();
         response = doDelete(uri, queryParams, DEFAULT_HTTP_TIMEOUT_SEC);
         assertEquals(response.getStatusCode(), Status.OK.getStatusCode());
 
         // Uncancel
-        uri = BaseJaxrsResource.SUBSCRIPTIONS_PATH + "/" + subscriptionJson.getSubscriptionId().toString() + "/uncancel";
+        uri = JaxrsResource.SUBSCRIPTIONS_PATH + "/" + subscriptionJson.getSubscriptionId().toString() + "/uncancel";
         response = doPut(uri, baseJson, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
         Assert.assertEquals(response.getStatusCode(), Status.OK.getStatusCode());
     }
     
     @Test(groups="slow", enabled=true)
     public void testWithNonExistentSubscription() throws Exception {
-        String uri = BaseJaxrsResource.SUBSCRIPTIONS_PATH + "/" + UUID.randomUUID().toString();
+        String uri = JaxrsResource.SUBSCRIPTIONS_PATH + "/" + UUID.randomUUID().toString();
         SubscriptionJsonNoEvents subscriptionJson = new SubscriptionJsonNoEvents(null, UUID.randomUUID().toString(), null, "Pistol", ProductCategory.BASE.toString(), BillingPeriod.MONTHLY.toString(), PriceListSet.DEFAULT_PRICELIST_NAME, null);
         String baseJson = mapper.writeValueAsString(subscriptionJson);
         
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 c1f460a..da8318f 100644
--- a/server/src/test/java/com/ning/billing/jaxrs/TestTag.java
+++ b/server/src/test/java/com/ning/billing/jaxrs/TestTag.java
@@ -22,13 +22,13 @@ import java.util.List;
 
 import javax.ws.rs.core.Response.Status;
 
+import com.ning.billing.jaxrs.resources.JaxrsResource;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.testng.annotations.Test;
 
 import com.fasterxml.jackson.core.type.TypeReference;
 import com.ning.billing.jaxrs.json.TagDefinitionJson;
-import com.ning.billing.jaxrs.resources.BaseJaxrsResource;
 import com.ning.http.client.Response;
 
 public class TestTag extends TestJaxrsBase {
@@ -40,7 +40,7 @@ public class TestTag extends TestJaxrsBase {
     
         TagDefinitionJson input = new TagDefinitionJson("blue", "realxing color");
         String baseJson = mapper.writeValueAsString(input);
-        Response response = doPost(BaseJaxrsResource.TAG_DEFINITIONS_PATH, baseJson, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
+        Response response = doPost(JaxrsResource.TAG_DEFINITIONS_PATH, baseJson, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
         assertEquals(response.getStatusCode(), Status.CREATED.getStatusCode());
 
         String location = response.getHeader("Location");
@@ -59,7 +59,7 @@ public class TestTag extends TestJaxrsBase {
     @Test(groups="slow", enabled=true)
     public void testMultipleTagDefinitionOk() throws Exception {
     
-        Response response = doGet(BaseJaxrsResource.TAG_DEFINITIONS_PATH, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
+        Response response = doGet(JaxrsResource.TAG_DEFINITIONS_PATH, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
         assertEquals(response.getStatusCode(), Status.OK.getStatusCode());
         String baseJson = response.getResponseBody();
         
@@ -68,25 +68,25 @@ public class TestTag extends TestJaxrsBase {
         
         TagDefinitionJson input = new TagDefinitionJson("blue", "realxing color");
         baseJson = mapper.writeValueAsString(input);
-        response = doPost(BaseJaxrsResource.TAG_DEFINITIONS_PATH, baseJson, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
+        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);
-        response = doPost(BaseJaxrsResource.TAG_DEFINITIONS_PATH, baseJson, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
+        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);
-        response = doPost(BaseJaxrsResource.TAG_DEFINITIONS_PATH, baseJson, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
+        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 realxing color");
         baseJson = mapper.writeValueAsString(input);
-        response = doPost(BaseJaxrsResource.TAG_DEFINITIONS_PATH, baseJson, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
+        response = doPost(JaxrsResource.TAG_DEFINITIONS_PATH, baseJson, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
         assertEquals(response.getStatusCode(), Status.CREATED.getStatusCode());
 
-        response = doGet(BaseJaxrsResource.TAG_DEFINITIONS_PATH, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
+        response = doGet(JaxrsResource.TAG_DEFINITIONS_PATH, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
         assertEquals(response.getStatusCode(), Status.OK.getStatusCode());
         baseJson = response.getResponseBody();
         
@@ -97,11 +97,11 @@ public class TestTag extends TestJaxrsBase {
         // STEPH currently broken Tag API does not work as expected...
         
         /*
-        String uri = BaseJaxrsResource.TAG_DEFINITIONS_PATH + "/green"; 
+        String uri = JaxrsResource.TAG_DEFINITIONS_PATH + "/green";
         response = doDelete(uri, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
         assertEquals(response.getStatusCode(), Status.NO_CONTENT.getStatusCode());
     
-        response = doGet(BaseJaxrsResource.TAG_DEFINITIONS_PATH, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
+        response = doGet(JaxrsResource.TAG_DEFINITIONS_PATH, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
         assertEquals(response.getStatusCode(), Status.OK.getStatusCode());
         baseJson = response.getResponseBody();
         

util/pom.xml 18(+9 -9)

diff --git a/util/pom.xml b/util/pom.xml
index 74dcdd3..2031104 100644
--- a/util/pom.xml
+++ b/util/pom.xml
@@ -13,7 +13,7 @@
     <parent>
         <groupId>com.ning.billing</groupId>
         <artifactId>killbill</artifactId>
-        <version>0.1.12-SNAPSHOT</version>
+        <version>0.1.13-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <artifactId>killbill-util</artifactId>
@@ -60,14 +60,6 @@
             <artifactId>joda-time</artifactId>
         </dependency>
         <dependency>
-            <groupId>org.codehaus.jackson</groupId>
-            <artifactId>jackson-core-asl</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.codehaus.jackson</groupId>
-            <artifactId>jackson-mapper-asl</artifactId>
-        </dependency>
-        <dependency>
             <groupId>org.testng</groupId>
             <artifactId>testng</artifactId>
             <scope>test</scope>
@@ -107,6 +99,14 @@
             <groupId>commons-io</groupId>
             <artifactId>commons-io</artifactId>
         </dependency>
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.fasterxml.jackson.datatype</groupId>
+            <artifactId>jackson-datatype-joda</artifactId>
+        </dependency>
     </dependencies>
     <build>
         <plugins>
diff --git a/util/src/main/java/com/ning/billing/util/bus/PersistentBus.java b/util/src/main/java/com/ning/billing/util/bus/PersistentBus.java
index 92b35d7..a609c80 100644
--- a/util/src/main/java/com/ning/billing/util/bus/PersistentBus.java
+++ b/util/src/main/java/com/ning/billing/util/bus/PersistentBus.java
@@ -15,15 +15,12 @@
  */
 package com.ning.billing.util.bus;
 
-
 import java.util.Collections;
 import java.util.Date;
 import java.util.List;
 import java.util.concurrent.Executors;
 import java.util.concurrent.ThreadFactory;
 
-import org.codehaus.jackson.map.ObjectMapper;
-import org.codehaus.jackson.map.SerializationConfig;
 import org.skife.jdbi.v2.IDBI;
 import org.skife.jdbi.v2.Transaction;
 import org.skife.jdbi.v2.TransactionStatus;
@@ -33,16 +30,13 @@ import org.slf4j.LoggerFactory;
 
 import com.google.common.eventbus.EventBus;
 import com.google.inject.Inject;
-import com.google.inject.name.Named;
-import com.ning.billing.config.PersistentQueueConfig;
 import com.ning.billing.util.Hostname;
 import com.ning.billing.util.bus.dao.BusEventEntry;
 import com.ning.billing.util.bus.dao.PersistentBusSqlDao;
 import com.ning.billing.util.clock.Clock;
-import com.ning.billing.util.glue.BusModule;
+import com.ning.billing.util.jackson.ObjectMapper;
 import com.ning.billing.util.queue.PersistentQueueBase;
 
-
 public class PersistentBus extends PersistentQueueBase implements Bus {
 
     private final static long DELTA_IN_PROCESSING_TIME_MS = 1000L * 60L * 5L; // 5 minutes
@@ -52,13 +46,11 @@ public class PersistentBus extends PersistentQueueBase implements Bus {
     
     private final PersistentBusSqlDao dao;
     
-    private final ObjectMapper objectMapper;
+    private final ObjectMapper objectMapper = new ObjectMapper();
     private final EventBusDelegate eventBusDelegate;
     private final Clock clock;
     private final String hostname;
-    
 
-    
     private static final class EventBusDelegate extends EventBus {
         public EventBusDelegate(String busName) {
             super(busName);
@@ -92,8 +84,6 @@ public class PersistentBus extends PersistentQueueBase implements Bus {
         }), config.getNbThreads(), config);
         this.dao = dbi.onDemand(PersistentBusSqlDao.class);
         this.clock = clock;
-        this.objectMapper = new ObjectMapper();
-        this.objectMapper.disable(SerializationConfig.Feature.WRITE_DATES_AS_TIMESTAMPS);
         this.eventBusDelegate = new EventBusDelegate("Killbill EventBus");
         this.hostname = Hostname.get();
     }
diff --git a/util/src/main/java/com/ning/billing/util/dao/AuditedCollectionDaoBase.java b/util/src/main/java/com/ning/billing/util/dao/AuditedCollectionDaoBase.java
index 10cd646..ba7084c 100644
--- a/util/src/main/java/com/ning/billing/util/dao/AuditedCollectionDaoBase.java
+++ b/util/src/main/java/com/ning/billing/util/dao/AuditedCollectionDaoBase.java
@@ -20,6 +20,7 @@ import com.ning.billing.util.ChangeType;
 import com.ning.billing.util.callcontext.CallContext;
 import com.ning.billing.util.entity.Entity;
 import com.ning.billing.util.entity.collection.dao.UpdatableEntityCollectionSqlDao;
+import org.skife.jdbi.v2.sqlobject.mixins.Transactional;
 import org.skife.jdbi.v2.sqlobject.mixins.Transmogrifier;
 
 import java.util.ArrayList;
diff --git a/util/src/main/java/com/ning/billing/util/dao/TableName.java b/util/src/main/java/com/ning/billing/util/dao/TableName.java
index 28a070a..9253107 100644
--- a/util/src/main/java/com/ning/billing/util/dao/TableName.java
+++ b/util/src/main/java/com/ning/billing/util/dao/TableName.java
@@ -22,7 +22,6 @@ public enum TableName {
     ACCOUNT_EMAIL_HISTORY("account_email_history"),
     BUNDLES("bundles"),
     CUSTOM_FIELD_HISTORY("custom_field_history"),
-    ENTITLEMENT_EVENTS("entitlement_events"),
     FIXED_INVOICE_ITEMS("fixed_invoice_items"),
     INVOICE_PAYMENTS("invoice_payments"),
     INVOICES("invoices"),
@@ -31,6 +30,7 @@ public enum TableName {
     PAYMENTS("payments"),
     RECURRING_INVOICE_ITEMS("recurring_invoice_items"),
     SUBSCRIPTIONS("subscriptions"),
+    SUBSCRIPTION_EVENTS("subscription_events"),
     TAG_HISTORY("tag_history");
     
     private final String tableName;
diff --git a/util/src/main/java/com/ning/billing/util/jackson/ObjectMapper.java b/util/src/main/java/com/ning/billing/util/jackson/ObjectMapper.java
new file mode 100644
index 0000000..42a1758
--- /dev/null
+++ b/util/src/main/java/com/ning/billing/util/jackson/ObjectMapper.java
@@ -0,0 +1,27 @@
+/*
+ * 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.jackson;
+
+import com.fasterxml.jackson.databind.SerializationFeature;
+import com.fasterxml.jackson.datatype.joda.JodaModule;
+
+public class ObjectMapper extends com.fasterxml.jackson.databind.ObjectMapper {
+    public ObjectMapper() {
+        this.registerModule(new JodaModule());
+        this.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
+    }
+}
diff --git a/util/src/test/java/com/ning/billing/mock/MockAccountBuilder.java b/util/src/test/java/com/ning/billing/mock/MockAccountBuilder.java
index a9cc6ec..2546757 100644
--- a/util/src/test/java/com/ning/billing/mock/MockAccountBuilder.java
+++ b/util/src/test/java/com/ning/billing/mock/MockAccountBuilder.java
@@ -18,7 +18,6 @@ package com.ning.billing.mock;
 
 import java.util.UUID;
 
-import org.apache.commons.lang.NotImplementedException;
 import org.joda.time.DateTimeZone;
 
 import com.ning.billing.account.api.Account;
@@ -279,7 +278,7 @@ public class MockAccountBuilder {
 
             @Override
             public MutableAccountData toMutableAccountData() {
-                throw new NotImplementedException();
+                throw new UnsupportedOperationException();
             }
         };
     }
diff --git a/util/src/test/java/com/ning/billing/util/bus/TestEventBusBase.java b/util/src/test/java/com/ning/billing/util/bus/TestEventBusBase.java
index ddc89ed..bd74b44 100644
--- a/util/src/test/java/com/ning/billing/util/bus/TestEventBusBase.java
+++ b/util/src/test/java/com/ning/billing/util/bus/TestEventBusBase.java
@@ -17,21 +17,19 @@ package com.ning.billing.util.bus;
 
 import java.util.UUID;
 
-import org.codehaus.jackson.annotate.JsonCreator;
-import org.codehaus.jackson.annotate.JsonIgnore;
-import org.codehaus.jackson.annotate.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.testng.Assert;
 import org.testng.annotations.AfterClass;
 import org.testng.annotations.BeforeClass;
-import org.testng.annotations.Test;
 
 import com.google.common.eventbus.Subscribe;
 import com.google.inject.Inject;
 import com.ning.billing.util.bus.BusEvent.BusEventType;
 
-
 public class TestEventBusBase {
 
     protected static final Logger log = LoggerFactory.getLogger(TestEventBusBase.class);