killbill-memoizeit

Merge branch 'master' into entitlement Initial merge from

8/20/2013 6:20:28 PM

Changes

.idea/libraries/Maven__com_ning_billing_killbill_entitlement_test_jar_tests_0_3_6_SNAPSHOT.xml 15(+0 -15)

.idea/libraries/Maven__com_ning_billing_killbill_junction_test_jar_tests_0_3_6_SNAPSHOT.xml 13(+0 -13)

.idea/libraries/Maven__com_ning_billing_killbill_payment_test_jar_tests_0_3_6_SNAPSHOT.xml 13(+0 -13)

.idea/libraries/Maven__com_ning_billing_plugin_killbill_plugin_api_notification_0_3_1_SNAPSHOT.xml 13(+0 -13)

.idea/libraries/Maven__com_ning_billing_plugin_killbill_plugin_api_payment_0_3_1_SNAPSHOT.xml 13(+0 -13)

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

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

beatrix/pom.xml 8(+6 -2)

bin/start-server 2(+1 -1)

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

entitlement/src/test/java/com/ning/billing/entitlement/block/TestDefaultBlockingApi.java 74(+0 -74)

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

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

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

NEWS 16(+16 -0)

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

overdue/pom.xml 8(+6 -2)

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

pom.xml 4(+2 -2)

README.md 63(+1 -62)

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

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

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

util/pom.xml 29(+27 -2)

util/src/main/java/com/ning/billing/util/config/MeterConfig.java 123(+0 -123)

util/src/main/java/com/ning/billing/util/globallocker/MySqlGlobalLocker.java 106(+0 -106)

util/src/main/java/com/ning/billing/util/globallocker/MySqlGlobalLockerDao.java 46(+0 -46)

util/src/test/java/com/ning/billing/dbi/H2TestingHelper.java 92(+0 -92)

util/src/test/java/com/ning/billing/dbi/MysqlTestingHelper.java 162(+0 -162)

util/src/test/java/com/ning/billing/util/globallocker/MockGlobalLocker.java 75(+0 -75)

Details

diff --git a/.idea/codeStyleSettings.xml b/.idea/codeStyleSettings.xml
index 0391fca..d2196b4 100644
--- a/.idea/codeStyleSettings.xml
+++ b/.idea/codeStyleSettings.xml
@@ -28,6 +28,7 @@
           </value>
         </option>
         <XML>
+          <option name="XML_ATTRIBUTE_WRAP" value="0" />
           <option name="XML_LEGACY_SETTINGS_IMPORTED" value="true" />
         </XML>
         <codeStyleSettings language="JAVA">
@@ -42,12 +43,213 @@
           <option name="ALIGN_MULTILINE_THROWS_LIST" value="true" />
           <option name="ALIGN_MULTILINE_EXTENDS_LIST" value="true" />
           <option name="ALIGN_MULTILINE_METHOD_BRACKETS" value="true" />
+          <option name="ALIGN_MULTILINE_ARRAY_INITIALIZER_EXPRESSION" value="true" />
           <option name="KEEP_SIMPLE_METHODS_IN_ONE_LINE" value="true" />
           <option name="KEEP_SIMPLE_CLASSES_IN_ONE_LINE" value="true" />
           <option name="IF_BRACE_FORCE" value="3" />
           <option name="DOWHILE_BRACE_FORCE" value="3" />
           <option name="WHILE_BRACE_FORCE" value="3" />
           <option name="FOR_BRACE_FORCE" value="3" />
+          <arrangement>
+            <groups>
+              <group>
+                <type>GETTERS_AND_SETTERS</type>
+                <order>KEEP</order>
+              </group>
+            </groups>
+            <rules>
+              <rule>
+                <match>
+                  <AND>
+                    <TYPE>FIELD</TYPE>
+                    <MODIFIER>PUBLIC</MODIFIER>
+                    <MODIFIER>STATIC</MODIFIER>
+                    <MODIFIER>FINAL</MODIFIER>
+                  </AND>
+                </match>
+              </rule>
+              <rule>
+                <match>
+                  <AND>
+                    <TYPE>FIELD</TYPE>
+                    <MODIFIER>PROTECTED</MODIFIER>
+                    <MODIFIER>STATIC</MODIFIER>
+                    <MODIFIER>FINAL</MODIFIER>
+                  </AND>
+                </match>
+              </rule>
+              <rule>
+                <match>
+                  <AND>
+                    <TYPE>FIELD</TYPE>
+                    <MODIFIER>PACKAGE_PRIVATE</MODIFIER>
+                    <MODIFIER>STATIC</MODIFIER>
+                    <MODIFIER>FINAL</MODIFIER>
+                  </AND>
+                </match>
+              </rule>
+              <rule>
+                <match>
+                  <AND>
+                    <TYPE>FIELD</TYPE>
+                    <MODIFIER>PRIVATE</MODIFIER>
+                    <MODIFIER>STATIC</MODIFIER>
+                    <MODIFIER>FINAL</MODIFIER>
+                  </AND>
+                </match>
+              </rule>
+              <rule>
+                <match>
+                  <AND>
+                    <TYPE>FIELD</TYPE>
+                    <MODIFIER>PUBLIC</MODIFIER>
+                    <MODIFIER>STATIC</MODIFIER>
+                  </AND>
+                </match>
+              </rule>
+              <rule>
+                <match>
+                  <AND>
+                    <TYPE>FIELD</TYPE>
+                    <MODIFIER>PROTECTED</MODIFIER>
+                    <MODIFIER>STATIC</MODIFIER>
+                  </AND>
+                </match>
+              </rule>
+              <rule>
+                <match>
+                  <AND>
+                    <TYPE>FIELD</TYPE>
+                    <MODIFIER>PACKAGE_PRIVATE</MODIFIER>
+                    <MODIFIER>STATIC</MODIFIER>
+                  </AND>
+                </match>
+              </rule>
+              <rule>
+                <match>
+                  <AND>
+                    <TYPE>FIELD</TYPE>
+                    <MODIFIER>PRIVATE</MODIFIER>
+                    <MODIFIER>STATIC</MODIFIER>
+                  </AND>
+                </match>
+              </rule>
+              <rule>
+                <match>
+                  <AND>
+                    <TYPE>FIELD</TYPE>
+                    <MODIFIER>PUBLIC</MODIFIER>
+                    <MODIFIER>FINAL</MODIFIER>
+                  </AND>
+                </match>
+              </rule>
+              <rule>
+                <match>
+                  <AND>
+                    <TYPE>FIELD</TYPE>
+                    <MODIFIER>PROTECTED</MODIFIER>
+                    <MODIFIER>FINAL</MODIFIER>
+                  </AND>
+                </match>
+              </rule>
+              <rule>
+                <match>
+                  <AND>
+                    <TYPE>FIELD</TYPE>
+                    <MODIFIER>PACKAGE_PRIVATE</MODIFIER>
+                    <MODIFIER>FINAL</MODIFIER>
+                  </AND>
+                </match>
+              </rule>
+              <rule>
+                <match>
+                  <AND>
+                    <TYPE>FIELD</TYPE>
+                    <MODIFIER>PRIVATE</MODIFIER>
+                    <MODIFIER>FINAL</MODIFIER>
+                  </AND>
+                </match>
+              </rule>
+              <rule>
+                <match>
+                  <AND>
+                    <TYPE>FIELD</TYPE>
+                    <MODIFIER>PUBLIC</MODIFIER>
+                  </AND>
+                </match>
+              </rule>
+              <rule>
+                <match>
+                  <AND>
+                    <TYPE>FIELD</TYPE>
+                    <MODIFIER>PROTECTED</MODIFIER>
+                  </AND>
+                </match>
+              </rule>
+              <rule>
+                <match>
+                  <AND>
+                    <TYPE>FIELD</TYPE>
+                    <MODIFIER>PACKAGE_PRIVATE</MODIFIER>
+                  </AND>
+                </match>
+              </rule>
+              <rule>
+                <match>
+                  <AND>
+                    <TYPE>FIELD</TYPE>
+                    <MODIFIER>PRIVATE</MODIFIER>
+                  </AND>
+                </match>
+              </rule>
+              <rule>
+                <match>
+                  <TYPE>FIELD</TYPE>
+                </match>
+              </rule>
+              <rule>
+                <match>
+                  <TYPE>CONSTRUCTOR</TYPE>
+                </match>
+              </rule>
+              <rule>
+                <match>
+                  <AND>
+                    <TYPE>METHOD</TYPE>
+                    <MODIFIER>STATIC</MODIFIER>
+                  </AND>
+                </match>
+              </rule>
+              <rule>
+                <match>
+                  <TYPE>METHOD</TYPE>
+                </match>
+              </rule>
+              <rule>
+                <match>
+                  <TYPE>ENUM</TYPE>
+                </match>
+              </rule>
+              <rule>
+                <match>
+                  <TYPE>INTERFACE</TYPE>
+                </match>
+              </rule>
+              <rule>
+                <match>
+                  <AND>
+                    <TYPE>CLASS</TYPE>
+                    <MODIFIER>STATIC</MODIFIER>
+                  </AND>
+                </match>
+              </rule>
+              <rule>
+                <match>
+                  <TYPE>CLASS</TYPE>
+                </match>
+              </rule>
+            </rules>
+          </arrangement>
         </codeStyleSettings>
       </value>
     </option>
diff --git a/.idea/dictionaries/pierre.xml b/.idea/dictionaries/pierre.xml
index 118b145..e586f6b 100644
--- a/.idea/dictionaries/pierre.xml
+++ b/.idea/dictionaries/pierre.xml
@@ -1,3 +1,11 @@
 <component name="ProjectDictionaryState">
-  <dictionary name="pierre" />
+  <dictionary name="pierre">
+    <words>
+      <w>aoped</w>
+      <w>jdbc</w>
+      <w>killbill</w>
+      <w>shiro</w>
+      <w>stephane</w>
+    </words>
+  </dictionary>
 </component>
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
index 95037c1..e0ce11c 100644
--- a/.idea/inspectionProfiles/Project_Default.xml
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -2,6 +2,7 @@
   <profile version="1.0" is_locked="false">
     <option name="myName" value="Project Default" />
     <option name="myLocal" value="false" />
+    <inspection_tool class="CheckTagEmptyBody" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="ConfusingOctalEscape" enabled="true" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="ControlFlowStatementWithoutBraces" enabled="true" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="CyclicClassDependency" enabled="true" level="WARNING" enabled_by_default="true" />
@@ -34,5 +35,16 @@
     <inspection_tool class="UnnecessaryConstantArrayCreationExpression" enabled="true" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="UseOfJDBCDriverClass" enabled="true" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="UseOfSunClasses" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="groupsTestNG" enabled="true" level="WARNING" enabled_by_default="true">
+      <option name="groups">
+        <value>
+          <list size="3">
+            <item index="0" class="java.lang.String" itemvalue="slow" />
+            <item index="1" class="java.lang.String" itemvalue="fast" />
+            <item index="2" class="java.lang.String" itemvalue="mysql" />
+          </list>
+        </value>
+      </option>
+    </inspection_tool>
   </profile>
 </component>
\ No newline at end of file
diff --git a/account/killbill-account.iml b/account/killbill-account.iml
index 38da507..fc0f3d0 100644
--- a/account/killbill-account.iml
+++ b/account/killbill-account.iml
@@ -20,10 +20,10 @@
     <orderEntry type="library" scope="PROVIDED" name="Maven: javax.inject:javax.inject:1" level="project" />
     <orderEntry type="library" scope="PROVIDED" name="Maven: aopalliance:aopalliance:1.0" level="project" />
     <orderEntry type="library" scope="TEST" name="Maven: com.h2database:h2:1.3.158" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing:killbill-api:0.3.3-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing:killbill-api:0.6.0-SNAPSHOT" level="project" />
     <orderEntry type="library" name="Maven: joda-time:joda-time:2.0" level="project" />
     <orderEntry type="module" module-name="killbill-internal-api" />
-    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-payment:0.3.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-payment:0.4.0-SNAPSHOT" level="project" />
     <orderEntry type="library" name="Maven: org.skife.config:config-magic:0.14" level="project" />
     <orderEntry type="library" name="Maven: org.slf4j:slf4j-api:1.7.5" level="project" />
     <orderEntry type="module" module-name="killbill-util" />
@@ -32,13 +32,14 @@
     <orderEntry type="library" name="Maven: com.jolbox:bonecp:0.7.1.RELEASE" level="project" />
     <orderEntry type="library" name="Maven: com.mchange:c3p0:0.9.2" level="project" />
     <orderEntry type="library" name="Maven: com.mchange:mchange-commons-java:0.2.3.3" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-clock:0.1.7" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-queue:0.1.7" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-jdbi:0.1.7" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-clock:0.2.1" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-locker:0.2.1" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-queue:0.2.1" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-jdbi:0.2.1" level="project" />
     <orderEntry type="library" name="Maven: org.jdbi:jdbi:2.39.1" level="project" />
     <orderEntry type="library" name="Maven: com.yammer.metrics:metrics-core:2.1.2" level="project" />
     <orderEntry type="library" name="Maven: org.weakref:jmxutils:1.12" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-notification:0.3.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-notification:0.4.0-SNAPSHOT" level="project" />
     <orderEntry type="library" name="Maven: com.samskivert:jmustache:1.5" level="project" />
     <orderEntry type="library" name="Maven: net.sf.ehcache:ehcache-core:2.6.2" level="project" />
     <orderEntry type="library" scope="RUNTIME" name="Maven: org.antlr:stringtemplate:3.2.1" level="project" />
@@ -46,9 +47,16 @@
     <orderEntry type="library" name="Maven: org.apache.commons:commons-email:1.2" level="project" />
     <orderEntry type="library" name="Maven: javax.mail:mail:1.4.1" level="project" />
     <orderEntry type="library" name="Maven: javax.activation:activation:1.1" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.shiro:shiro-core:1.2.2" level="project" />
+    <orderEntry type="library" name="Maven: commons-beanutils:commons-beanutils:1.8.3" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.shiro:shiro-ehcache:1.2.2" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.shiro:shiro-guice:1.2.2" level="project" />
+    <orderEntry type="library" scope="PROVIDED" name="Maven: com.google.inject.extensions:guice-multibindings:3.0" level="project" />
+    <orderEntry type="library" name="Maven: org.slf4j:jcl-over-slf4j:1.7.5" level="project" />
     <orderEntry type="module" module-name="killbill-util" scope="TEST" production-on-test="" />
-    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-util:test-jar:tests:0.3.6-SNAPSHOT" level="project" />
-    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing.commons:killbill-clock:test-jar:tests:0.1.7" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-util:test-jar:tests:0.5.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing.commons:killbill-clock:test-jar:tests:0.2.1" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing.commons:killbill-embeddeddb:0.2.1" level="project" />
     <orderEntry type="library" scope="TEST" name="Maven: mysql:mysql-connector-mxj:5.0.12" level="project" />
     <orderEntry type="library" scope="TEST" name="Maven: mysql:mysql-connector-mxj-db-files:5.0.12" level="project" />
     <orderEntry type="library" scope="RUNTIME" name="Maven: mysql:mysql-connector-java:5.1.22" level="project" />

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

diff --git a/account/pom.xml b/account/pom.xml
index d497f5b..90a7a80 100644
--- a/account/pom.xml
+++ b/account/pom.xml
@@ -19,7 +19,7 @@
     <parent>
         <artifactId>killbill</artifactId>
         <groupId>com.ning.billing</groupId>
-        <version>0.3.6-SNAPSHOT</version>
+        <version>0.5.1-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <artifactId>killbill-account</artifactId>
@@ -83,6 +83,11 @@
         </dependency>
         <dependency>
             <groupId>com.ning.billing.commons</groupId>
+            <artifactId>killbill-embeddeddb</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.ning.billing.commons</groupId>
             <artifactId>killbill-queue</artifactId>
         </dependency>
         <dependency>
diff --git a/account/src/main/java/com/ning/billing/account/api/user/DefaultAccountUserApi.java b/account/src/main/java/com/ning/billing/account/api/user/DefaultAccountUserApi.java
index a7c1714..96d6191 100644
--- a/account/src/main/java/com/ning/billing/account/api/user/DefaultAccountUserApi.java
+++ b/account/src/main/java/com/ning/billing/account/api/user/DefaultAccountUserApi.java
@@ -64,7 +64,7 @@ public class DefaultAccountUserApi implements AccountUserApi {
         }
 
         final AccountModelDao account = new AccountModelDao(data);
-        accountDao.create(account, internalCallContextFactory.createInternalCallContext(account.getId(), context));
+        accountDao.create(account, internalCallContextFactory.createInternalCallContext(context));
 
         return new DefaultAccount(account);
     }
@@ -90,6 +90,17 @@ public class DefaultAccountUserApi implements AccountUserApi {
     }
 
     @Override
+    public List<Account> searchAccounts(final String searchKey, final TenantContext context) {
+        final List<AccountModelDao> accountModelDaos = accountDao.searchAccounts(searchKey, internalCallContextFactory.createInternalTenantContext(context));
+        return ImmutableList.<Account>copyOf(Collections2.transform(accountModelDaos, new Function<AccountModelDao, Account>() {
+            @Override
+            public Account apply(final AccountModelDao input) {
+                return new DefaultAccount(input);
+            }
+        }));
+    }
+
+    @Override
     public List<Account> getAccounts(final TenantContext context) {
         final List<AccountModelDao> accountModelDaos = accountDao.get(internalCallContextFactory.createInternalTenantContext(context));
         return ImmutableList.<Account>copyOf(Collections2.transform(accountModelDaos, new Function<AccountModelDao, Account>() {
diff --git a/account/src/main/java/com/ning/billing/account/dao/AccountDao.java b/account/src/main/java/com/ning/billing/account/dao/AccountDao.java
index 9f11a5e..f390c11 100644
--- a/account/src/main/java/com/ning/billing/account/dao/AccountDao.java
+++ b/account/src/main/java/com/ning/billing/account/dao/AccountDao.java
@@ -29,6 +29,8 @@ public interface AccountDao extends EntityDao<AccountModelDao, Account, AccountA
 
     public AccountModelDao getAccountByKey(String key, InternalTenantContext context);
 
+    public List<AccountModelDao> searchAccounts(String searchKey, InternalTenantContext context);
+
     /**
      * @throws AccountApiException when externalKey is null
      */
diff --git a/account/src/main/java/com/ning/billing/account/dao/AccountSqlDao.java b/account/src/main/java/com/ning/billing/account/dao/AccountSqlDao.java
index f49f454..01aa04e 100644
--- a/account/src/main/java/com/ning/billing/account/dao/AccountSqlDao.java
+++ b/account/src/main/java/com/ning/billing/account/dao/AccountSqlDao.java
@@ -16,12 +16,14 @@
 
 package com.ning.billing.account.dao;
 
+import java.util.List;
 import java.util.UUID;
 
 import org.skife.jdbi.v2.sqlobject.Bind;
 import org.skife.jdbi.v2.sqlobject.BindBean;
 import org.skife.jdbi.v2.sqlobject.SqlQuery;
 import org.skife.jdbi.v2.sqlobject.SqlUpdate;
+import org.skife.jdbi.v2.sqlobject.customizers.Define;
 
 import com.ning.billing.account.api.Account;
 import com.ning.billing.util.audit.ChangeType;
@@ -39,6 +41,10 @@ public interface AccountSqlDao extends EntitySqlDao<AccountModelDao, Account> {
                                            @BindBean final InternalTenantContext context);
 
     @SqlQuery
+    public List<AccountModelDao> searchAccounts(@Define("searchKey") final String searchKey,
+                                                @BindBean final InternalTenantContext context);
+
+    @SqlQuery
     public UUID getIdFromKey(@Bind("externalKey") final String key,
                              @BindBean final InternalTenantContext context);
 
diff --git a/account/src/main/java/com/ning/billing/account/dao/DefaultAccountDao.java b/account/src/main/java/com/ning/billing/account/dao/DefaultAccountDao.java
index 76aa8cc..d3f77ed 100644
--- a/account/src/main/java/com/ning/billing/account/dao/DefaultAccountDao.java
+++ b/account/src/main/java/com/ning/billing/account/dao/DefaultAccountDao.java
@@ -104,6 +104,16 @@ public class DefaultAccountDao extends EntityDaoBase<AccountModelDao, Account, A
     }
 
     @Override
+    public List<AccountModelDao> searchAccounts(final String searchKey, final InternalTenantContext context) {
+        return transactionalSqlDao.execute(new EntitySqlDaoTransactionWrapper<List<AccountModelDao>>() {
+            @Override
+            public List<AccountModelDao> inTransaction(final EntitySqlDaoWrapperFactory<EntitySqlDao> entitySqlDaoWrapperFactory) throws Exception {
+                return entitySqlDaoWrapperFactory.become(AccountSqlDao.class).searchAccounts(searchKey, context);
+            }
+        });
+    }
+
+    @Override
     public UUID getIdFromKey(final String externalKey, final InternalTenantContext context) throws AccountApiException {
         if (externalKey == null) {
             throw new AccountApiException(ErrorCode.ACCOUNT_CANNOT_MAP_NULL_KEY, "");
diff --git a/account/src/main/resources/com/ning/billing/account/dao/AccountSqlDao.sql.stg b/account/src/main/resources/com/ning/billing/account/dao/AccountSqlDao.sql.stg
index 5ed297b..630f1dc 100644
--- a/account/src/main/resources/com/ning/billing/account/dao/AccountSqlDao.sql.stg
+++ b/account/src/main/resources/com/ning/billing/account/dao/AccountSqlDao.sql.stg
@@ -80,14 +80,30 @@ updatePaymentMethod() ::= <<
     WHERE id = :id <AND_CHECK_TENANT()>;
 >>
 
-
-
 getAccountByKey() ::= <<
     select <allTableFields()>
     from accounts
     where external_key = :externalKey <AND_CHECK_TENANT()>;
 >>
 
+searchAccounts(searchKey) ::= <<
+select <allTableFields()>
+from accounts
+where name like ('%<searchKey>%') <AND_CHECK_TENANT()>
+union
+select <allTableFields()>
+from accounts
+where email like ('%<searchKey>%') <AND_CHECK_TENANT()>
+union
+select <allTableFields()>
+from accounts
+where external_key like ('%<searchKey>%') <AND_CHECK_TENANT()>
+union
+select <allTableFields()>
+from accounts
+where company_name like ('%<searchKey>%') <AND_CHECK_TENANT()>
+;
+>>
 
 getIdFromKey() ::= <<
     SELECT id
diff --git a/account/src/test/java/com/ning/billing/account/dao/MockAccountDao.java b/account/src/test/java/com/ning/billing/account/dao/MockAccountDao.java
index 8d10192..e4e3aa3 100644
--- a/account/src/test/java/com/ning/billing/account/dao/MockAccountDao.java
+++ b/account/src/test/java/com/ning/billing/account/dao/MockAccountDao.java
@@ -16,6 +16,7 @@
 
 package com.ning.billing.account.dao;
 
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.UUID;
@@ -102,6 +103,20 @@ public class MockAccountDao extends MockEntityDaoBase<AccountModelDao, Account, 
     }
 
     @Override
+    public List<AccountModelDao> searchAccounts(final String searchKey, final InternalTenantContext context) {
+        final List<AccountModelDao> results = new LinkedList<AccountModelDao>();
+        for (final AccountModelDao account : get(context)) {
+            if ((account.getName() != null && account.getName().contains(searchKey)) ||
+                (account.getEmail() != null && account.getEmail().contains(searchKey)) ||
+                (account.getExternalKey() != null && account.getExternalKey().contains(searchKey)) ||
+                (account.getCompanyName() != null && account.getCompanyName().contains(searchKey))) {
+                results.add(account);
+            }
+        }
+        return results;
+    }
+
+    @Override
     public UUID getIdFromKey(final String externalKey, final InternalTenantContext context) {
         final AccountModelDao account = getAccountByKey(externalKey, context);
         return account == null ? null : account.getId();
diff --git a/api/killbill-internal-api.iml b/api/killbill-internal-api.iml
index e8866bf..8c2260d 100644
--- a/api/killbill-internal-api.iml
+++ b/api/killbill-internal-api.iml
@@ -9,11 +9,15 @@
     </content>
     <orderEntry type="inheritedJdk" />
     <orderEntry type="sourceFolder" forTests="false" />
+    <orderEntry type="library" name="Maven: com.ning.billing:killbill-api:0.6.0-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-payment:0.4.0-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing:killbill-api:0.6.0-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-payment:0.4.0-SNAPSHOT" level="project" />
     <orderEntry type="library" scope="PROVIDED" name="Maven: com.google.code.findbugs:jsr305:1.3.9" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing:killbill-api:0.3.3-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing:killbill-api:0.6.0-SNAPSHOT" level="project" />
     <orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-annotations:2.1.0" level="project" />
     <orderEntry type="library" name="Maven: joda-time:joda-time:2.0" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-payment:0.3.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-payment:0.4.0-SNAPSHOT" level="project" />
     <orderEntry type="library" scope="PROVIDED" name="Maven: javax.servlet:javax.servlet-api:3.0.1" level="project" />
     <orderEntry type="library" name="Maven: org.skife.config:config-magic:0.14" level="project" />
     <orderEntry type="library" name="Maven: org.slf4j:slf4j-api:1.7.5" level="project" />

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

diff --git a/api/pom.xml b/api/pom.xml
index 4c505f5..6c5aab6 100644
--- a/api/pom.xml
+++ b/api/pom.xml
@@ -19,7 +19,7 @@
     <parent>
         <artifactId>killbill</artifactId>
         <groupId>com.ning.billing</groupId>
-        <version>0.3.6-SNAPSHOT</version>
+        <version>0.5.1-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <artifactId>killbill-internal-api</artifactId>
diff --git a/api/src/main/java/com/ning/billing/overdue/OverdueState.java b/api/src/main/java/com/ning/billing/overdue/OverdueState.java
index 51ef0e2..b0682b1 100644
--- a/api/src/main/java/com/ning/billing/overdue/OverdueState.java
+++ b/api/src/main/java/com/ning/billing/overdue/OverdueState.java
@@ -18,9 +18,6 @@ package com.ning.billing.overdue;
 
 import org.joda.time.Period;
 
-import com.ning.billing.account.api.Account;
-import com.ning.billing.entitlement.api.Blockable;
-
 
 public interface OverdueState {
 
@@ -32,7 +29,7 @@ public interface OverdueState {
 
     public boolean disableEntitlementAndChangesBlocked();
 
-    public OverdueCancellationPolicicy getSubscriptionCancellationPolicy();
+    public OverdueCancellationPolicy getSubscriptionCancellationPolicy();
 
     public boolean blockChanges();
 
diff --git a/beatrix/killbill-beatrix.iml b/beatrix/killbill-beatrix.iml
index a1331a9..103ce23 100644
--- a/beatrix/killbill-beatrix.iml
+++ b/beatrix/killbill-beatrix.iml
@@ -12,6 +12,19 @@
     </content>
     <orderEntry type="inheritedJdk" />
     <orderEntry type="sourceFolder" forTests="false" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-account:test-jar:tests:0.4.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-payment:0.3.0" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-invoice:test-jar:tests:0.4.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-junction:test-jar:tests:0.4.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-payment:test-jar:tests:0.4.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-account:test-jar:tests:0.5.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing:killbill-api:0.6.0-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-payment:0.4.0-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-notification:0.4.0-SNAPSHOT" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-invoice:test-jar:tests:0.5.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-junction:test-jar:tests:0.5.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-util:test-jar:tests:0.5.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-payment:test-jar:tests:0.5.1-SNAPSHOT" level="project" />
     <orderEntry type="library" scope="PROVIDED" name="Maven: com.google.guava:guava:14.0.1" level="project" />
     <orderEntry type="library" scope="PROVIDED" name="Maven: com.google.inject:guice:3.0" level="project" />
     <orderEntry type="library" scope="PROVIDED" name="Maven: javax.inject:javax.inject:1" level="project" />
@@ -25,27 +38,28 @@
     <orderEntry type="library" name="Maven: com.jolbox:bonecp:0.7.1.RELEASE" level="project" />
     <orderEntry type="library" name="Maven: org.slf4j:slf4j-api:1.7.5" level="project" />
     <orderEntry type="module" module-name="killbill-account" scope="TEST" production-on-test="" />
-    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-account:test-jar:tests:0.3.6-SNAPSHOT" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-account:test-jar:tests:0.5.1-SNAPSHOT" level="project" />
     <orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-annotations:2.1.0" level="project" />
     <orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-databind:2.1.0" level="project" />
     <orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-core:2.1.0" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing:killbill-api:0.3.3-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing:killbill-api:0.6.0-SNAPSHOT" level="project" />
     <orderEntry type="library" name="Maven: joda-time:joda-time:2.0" level="project" />
     <orderEntry type="module" module-name="killbill-internal-api" />
-    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-payment:0.3.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-payment:0.4.0-SNAPSHOT" level="project" />
     <orderEntry type="library" name="Maven: org.skife.config:config-magic:0.14" level="project" />
     <orderEntry type="module" module-name="killbill-util" />
     <orderEntry type="library" name="Maven: com.fasterxml.jackson.dataformat:jackson-dataformat-csv:2.1.0" level="project" />
     <orderEntry type="library" name="Maven: com.fasterxml.jackson.datatype:jackson-datatype-joda:2.0.1" level="project" />
     <orderEntry type="library" name="Maven: com.mchange:c3p0:0.9.2" level="project" />
     <orderEntry type="library" name="Maven: com.mchange:mchange-commons-java:0.2.3.3" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-clock:0.1.7" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-queue:0.1.7" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-jdbi:0.1.7" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-clock:0.2.1" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-locker:0.2.1" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-queue:0.2.1" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-jdbi:0.2.1" level="project" />
     <orderEntry type="library" name="Maven: org.jdbi:jdbi:2.39.1" level="project" />
     <orderEntry type="library" name="Maven: com.yammer.metrics:metrics-core:2.1.2" level="project" />
     <orderEntry type="library" name="Maven: org.weakref:jmxutils:1.12" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-notification:0.3.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-notification:0.4.0-SNAPSHOT" level="project" />
     <orderEntry type="library" name="Maven: com.samskivert:jmustache:1.5" level="project" />
     <orderEntry type="library" name="Maven: net.sf.ehcache:ehcache-core:2.6.2" level="project" />
     <orderEntry type="library" name="Maven: org.antlr:stringtemplate:3.2.1" level="project" />
@@ -53,16 +67,22 @@
     <orderEntry type="library" name="Maven: org.apache.commons:commons-email:1.2" level="project" />
     <orderEntry type="library" name="Maven: javax.mail:mail:1.4.1" level="project" />
     <orderEntry type="library" name="Maven: javax.activation:activation:1.1" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.shiro:shiro-core:1.2.2" level="project" />
+    <orderEntry type="library" name="Maven: commons-beanutils:commons-beanutils:1.8.3" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.shiro:shiro-ehcache:1.2.2" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.shiro:shiro-guice:1.2.2" level="project" />
+    <orderEntry type="library" scope="PROVIDED" name="Maven: com.google.inject.extensions:guice-multibindings:3.0" level="project" />
+    <orderEntry type="library" name="Maven: org.slf4j:jcl-over-slf4j:1.7.5" level="project" />
     <orderEntry type="module" module-name="killbill-account" scope="TEST" />
     <orderEntry type="module" module-name="killbill-catalog" />
     <orderEntry type="module" module-name="killbill-entitlement" />
     <orderEntry type="module" module-name="killbill-invoice" />
     <orderEntry type="module" module-name="killbill-invoice" scope="TEST" production-on-test="" />
-    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-invoice:test-jar:tests:0.3.6-SNAPSHOT" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-invoice:test-jar:tests:0.5.1-SNAPSHOT" level="project" />
     <orderEntry type="module" module-name="killbill-junction" />
     <orderEntry type="library" scope="RUNTIME" name="Maven: mysql:mysql-connector-java:5.1.22" level="project" />
     <orderEntry type="module" module-name="killbill-junction" scope="TEST" production-on-test="" />
-    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-junction:test-jar:tests:0.3.6-SNAPSHOT" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-junction:test-jar:tests:0.5.1-SNAPSHOT" level="project" />
     <orderEntry type="module" module-name="killbill-osgi" scope="TEST" />
     <orderEntry type="module" module-name="killbill-osgi-bundles-lib-killbill" scope="TEST" />
     <orderEntry type="library" scope="PROVIDED" name="Maven: com.google.code.findbugs:jsr305:1.3.9" level="project" />
@@ -71,23 +91,22 @@
     <orderEntry type="library" scope="TEST" name="Maven: org.apache.felix:org.apache.felix.framework:4.0.3" level="project" />
     <orderEntry type="library" scope="TEST" name="Maven: org.apache.felix:org.osgi.core:1.0.1" level="project" />
     <orderEntry type="module" module-name="killbill-osgi-bundles-jruby" scope="TEST" />
-    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing.commons:killbill-concurrent:0.1.7" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing.commons:killbill-concurrent:0.2.1" level="project" />
     <orderEntry type="library" scope="TEST" name="Maven: org.jruby:jruby-complete:1.7.1" level="project" />
     <orderEntry type="library" scope="TEST" name="Maven: org.osgi:org.osgi.core:4.3.1" level="project" />
     <orderEntry type="module" module-name="killbill-osgi-bundles-test-beatrix" scope="TEST" />
     <orderEntry type="module" module-name="killbill-osgi-bundles-test-payment" scope="TEST" />
     <orderEntry type="module" module-name="killbill-util" scope="TEST" production-on-test="" />
-    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-util:test-jar:tests:0.3.6-SNAPSHOT" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-util:test-jar:tests:0.5.1-SNAPSHOT" level="project" />
     <orderEntry type="module" module-name="killbill-overdue" scope="TEST" />
     <orderEntry type="module" module-name="killbill-payment" />
     <orderEntry type="module" module-name="killbill-payment" scope="TEST" production-on-test="" />
-    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-payment:test-jar:tests:0.3.6-SNAPSHOT" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-payment:test-jar:tests:0.5.1-SNAPSHOT" level="project" />
     <orderEntry type="module" module-name="killbill-subscription" />
     <orderEntry type="module" module-name="killbill-tenant" />
-    <orderEntry type="library" name="Maven: org.apache.shiro:shiro-core:1.2.1" level="project" />
-    <orderEntry type="library" name="Maven: commons-beanutils:commons-beanutils:1.8.3" level="project" />
     <orderEntry type="module" module-name="killbill-usage" />
-    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing.commons:killbill-clock:test-jar:tests:0.1.7" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing.commons:killbill-clock:test-jar:tests:0.2.1" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing.commons:killbill-embeddeddb:0.2.1" level="project" />
     <orderEntry type="library" name="Maven: commons-io:commons-io:2.1" level="project" />
     <orderEntry type="library" scope="TEST" name="Maven: javax.servlet:javax.servlet-api:3.0.1" level="project" />
     <orderEntry type="library" scope="TEST" name="Maven: mysql:mysql-connector-mxj:5.0.12" level="project" />

beatrix/pom.xml 8(+6 -2)

diff --git a/beatrix/pom.xml b/beatrix/pom.xml
index d0fa645..25b132e 100644
--- a/beatrix/pom.xml
+++ b/beatrix/pom.xml
@@ -19,7 +19,7 @@
     <parent>
         <artifactId>killbill</artifactId>
         <groupId>com.ning.billing</groupId>
-        <version>0.3.6-SNAPSHOT</version>
+        <version>0.5.1-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <artifactId>killbill-beatrix</artifactId>
@@ -161,13 +161,17 @@
         </dependency>
         <dependency>
             <groupId>com.ning.billing.commons</groupId>
+            <artifactId>killbill-embeddeddb</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.ning.billing.commons</groupId>
             <artifactId>killbill-queue</artifactId>
         </dependency>
         <dependency>
             <groupId>commons-io</groupId>
             <artifactId>commons-io</artifactId>
         </dependency>
-
         <dependency>
             <groupId>javax.servlet</groupId>
             <artifactId>javax.servlet-api</artifactId>
diff --git a/beatrix/src/main/java/com/ning/billing/beatrix/extbus/BeatrixListener.java b/beatrix/src/main/java/com/ning/billing/beatrix/extbus/BeatrixListener.java
index cdcd618..7946dd4 100644
--- a/beatrix/src/main/java/com/ning/billing/beatrix/extbus/BeatrixListener.java
+++ b/beatrix/src/main/java/com/ning/billing/beatrix/extbus/BeatrixListener.java
@@ -38,6 +38,7 @@ import com.ning.billing.util.callcontext.CallOrigin;
 import com.ning.billing.util.callcontext.InternalCallContext;
 import com.ning.billing.util.callcontext.InternalCallContextFactory;
 import com.ning.billing.util.callcontext.UserType;
+import com.ning.billing.util.dao.NonEntityDao;
 import com.ning.billing.util.events.AccountChangeInternalEvent;
 import com.ning.billing.util.events.AccountCreationInternalEvent;
 import com.ning.billing.util.events.BusInternalEvent;
@@ -72,17 +73,19 @@ public class
     private final PersistentBus externalBus;
     private final InternalCallContextFactory internalCallContextFactory;
     private final AccountInternalApi accountApi;
-
+    private final NonEntityDao nonEntityDao;
 
     protected final ObjectMapper objectMapper;
 
     @Inject
     public BeatrixListener(@Named(BeatrixModule.EXTERNAL_BUS) final PersistentBus externalBus,
                            final InternalCallContextFactory internalCallContextFactory,
-                           final AccountInternalApi accountApi) {
+                           final AccountInternalApi accountApi,
+                           final NonEntityDao nonEntityDao) {
         this.externalBus = externalBus;
         this.internalCallContextFactory = internalCallContextFactory;
         this.accountApi = accountApi;
+        this.nonEntityDao = nonEntityDao;
         this.objectMapper = new ObjectMapper();
         objectMapper.registerModule(new JodaModule());
         objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
@@ -237,7 +240,7 @@ public class
             default:
         }
         final UUID accountId = getAccountIdFromRecordId(event.getBusEventType(), objectId, context.getAccountRecordId(), context);
-        final UUID tenantId = context.toTenantContext().getTenantId();
+        final UUID tenantId = nonEntityDao.retrieveIdFromObject(context.getTenantRecordId(), ObjectType.TENANT);
 
         return eventBusType != null ?
                new DefaultBusExternalEvent(objectId, objectType, eventBusType, accountId, tenantId, context.getAccountRecordId(), context.getTenantRecordId(), context.getUserToken()) :
diff --git a/beatrix/src/main/java/com/ning/billing/beatrix/lifecycle/DefaultLifecycle.java b/beatrix/src/main/java/com/ning/billing/beatrix/lifecycle/DefaultLifecycle.java
index b4dbe24..04e324b 100644
--- a/beatrix/src/main/java/com/ning/billing/beatrix/lifecycle/DefaultLifecycle.java
+++ b/beatrix/src/main/java/com/ning/billing/beatrix/lifecycle/DefaultLifecycle.java
@@ -142,7 +142,7 @@ public class DefaultLifecycle implements Lifecycle {
 
     // Used to disable valid injection failure from unit tests
     protected void logWarn(final String msg, final Exception e) {
-        log.warn(msg);
+        log.warn(msg, e);
     }
 
     private Multimap<LifecycleLevel, LifecycleHandler<? extends KillbillService>> findAllHandlers(final KillbillService service) {
diff --git a/beatrix/src/test/java/com/ning/billing/beatrix/integration/osgi/TestBasicOSGIWithTestBundle.java b/beatrix/src/test/java/com/ning/billing/beatrix/integration/osgi/TestBasicOSGIWithTestBundle.java
index 744af92..56287f9 100644
--- a/beatrix/src/test/java/com/ning/billing/beatrix/integration/osgi/TestBasicOSGIWithTestBundle.java
+++ b/beatrix/src/test/java/com/ning/billing/beatrix/integration/osgi/TestBasicOSGIWithTestBundle.java
@@ -37,10 +37,11 @@ import org.testng.Assert;
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.Test;
 
+import com.ning.billing.DBTestingHelper;
 import com.ning.billing.account.api.Account;
 import com.ning.billing.beatrix.osgi.SetupBundleWithAssertion;
 import com.ning.billing.catalog.api.Currency;
-import com.ning.billing.dbi.DBTestingHelper;
+import com.ning.billing.commons.embeddeddb.EmbeddedDB;
 import com.ning.billing.osgi.api.OSGIServiceRegistration;
 import com.ning.billing.osgi.glue.OSGIDataSourceConfig;
 import com.ning.billing.payment.plugin.api.PaymentInfoPlugin;
@@ -67,10 +68,10 @@ public class TestBasicOSGIWithTestBundle extends TestOSGIBase {
 
     @BeforeClass(groups = "slow")
     public void beforeClass() throws Exception {
-
-        final String jdbcConnection = getDBTestingHelper().getJdbcConnectionString();
-        final String userName = DBTestingHelper.USERNAME;
-        final String userPwd = DBTestingHelper.PASSWORD;
+        // Can't use the injected helper as Guice hasn't injected anything yet
+        final String jdbcConnection = DBTestingHelper.get().getJdbcConnectionString();
+        final String userName = DBTestingHelper.get().getUsername();
+        final String userPwd = DBTestingHelper.get().getPassword();
 
         System.setProperty(OSGIDataSourceConfig.DATA_SOURCE_PROP_PREFIX + "jdbc.url", jdbcConnection);
         System.setProperty(OSGIDataSourceConfig.DATA_SOURCE_PROP_PREFIX + "jdbc.user", userName);
@@ -90,7 +91,7 @@ public class TestBasicOSGIWithTestBundle extends TestOSGIBase {
     public void testBundleTest() throws Exception {
 
         // At this point test bundle should have been started already
-        final TestActivatorWithAssertion assertTor = new TestActivatorWithAssertion(getDBI());
+        final TestActivatorWithAssertion assertTor = new TestActivatorWithAssertion(dbi);
         assertTor.assertPluginInitialized();
 
         // Create an account and expect test bundle listen to KB events and write the external name in its table

bin/start-server 2(+1 -1)

diff --git a/bin/start-server b/bin/start-server
index f6132f6..72e86b4 100755
--- a/bin/start-server
+++ b/bin/start-server
@@ -23,7 +23,7 @@ HERE=`cd \`dirname $0\`; pwd`
 TOP=$HERE/..
 SERVER=$TOP/server
 
-PROPERTIES="$SERVER/src/main/resources/killbill-server.properties"
+PROPERTIES=${PROPERTIES-"$SERVER/src/main/resources/killbill-server.properties"}
 
 DEBUG_OPTS_ECLIPSE=" -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=12345 "
 DEBUG_OPTS_ECLIPSE_WAIT=" -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=12345 "
diff --git a/catalog/killbill-catalog.iml b/catalog/killbill-catalog.iml
index 71e5645..a097881 100644
--- a/catalog/killbill-catalog.iml
+++ b/catalog/killbill-catalog.iml
@@ -12,16 +12,17 @@
     </content>
     <orderEntry type="inheritedJdk" />
     <orderEntry type="sourceFolder" forTests="false" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-payment:0.3.1-SNAPSHOT" level="project" />
     <orderEntry type="library" scope="PROVIDED" name="Maven: com.google.code.findbugs:jsr305:1.3.9" level="project" />
     <orderEntry type="library" scope="PROVIDED" name="Maven: com.google.guava:guava:14.0.1" level="project" />
     <orderEntry type="library" scope="PROVIDED" name="Maven: com.google.inject:guice:3.0" level="project" />
     <orderEntry type="library" scope="PROVIDED" name="Maven: javax.inject:javax.inject:1" level="project" />
     <orderEntry type="library" scope="PROVIDED" name="Maven: aopalliance:aopalliance:1.0" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing:killbill-api:0.3.3-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing:killbill-api:0.6.0-SNAPSHOT" level="project" />
     <orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-annotations:2.1.0" level="project" />
     <orderEntry type="library" name="Maven: joda-time:joda-time:2.0" level="project" />
     <orderEntry type="module" module-name="killbill-internal-api" />
-    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-payment:0.3.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-payment:0.4.0-SNAPSHOT" level="project" />
     <orderEntry type="library" name="Maven: org.skife.config:config-magic:0.14" level="project" />
     <orderEntry type="library" name="Maven: org.slf4j:slf4j-api:1.7.5" level="project" />
     <orderEntry type="module" module-name="killbill-util" />
@@ -32,14 +33,15 @@
     <orderEntry type="library" name="Maven: com.jolbox:bonecp:0.7.1.RELEASE" level="project" />
     <orderEntry type="library" name="Maven: com.mchange:c3p0:0.9.2" level="project" />
     <orderEntry type="library" name="Maven: com.mchange:mchange-commons-java:0.2.3.3" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-clock:0.1.7" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-queue:0.1.7" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-clock:0.2.1" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-locker:0.2.1" level="project" />
     <orderEntry type="library" scope="TEST" name="Maven: com.h2database:h2:1.3.158" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-jdbi:0.1.7" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-queue:0.2.1" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-jdbi:0.2.1" level="project" />
     <orderEntry type="library" name="Maven: org.jdbi:jdbi:2.39.1" level="project" />
     <orderEntry type="library" name="Maven: com.yammer.metrics:metrics-core:2.1.2" level="project" />
     <orderEntry type="library" name="Maven: org.weakref:jmxutils:1.12" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-notification:0.3.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-notification:0.4.0-SNAPSHOT" level="project" />
     <orderEntry type="library" name="Maven: com.samskivert:jmustache:1.5" level="project" />
     <orderEntry type="library" name="Maven: net.sf.ehcache:ehcache-core:2.6.2" level="project" />
     <orderEntry type="library" name="Maven: org.antlr:stringtemplate:3.2.1" level="project" />
@@ -47,9 +49,15 @@
     <orderEntry type="library" name="Maven: org.apache.commons:commons-email:1.2" level="project" />
     <orderEntry type="library" name="Maven: javax.mail:mail:1.4.1" level="project" />
     <orderEntry type="library" name="Maven: javax.activation:activation:1.1" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.shiro:shiro-core:1.2.2" level="project" />
+    <orderEntry type="library" name="Maven: commons-beanutils:commons-beanutils:1.8.3" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.shiro:shiro-ehcache:1.2.2" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.shiro:shiro-guice:1.2.2" level="project" />
+    <orderEntry type="library" scope="PROVIDED" name="Maven: com.google.inject.extensions:guice-multibindings:3.0" level="project" />
+    <orderEntry type="library" name="Maven: org.slf4j:jcl-over-slf4j:1.7.5" level="project" />
     <orderEntry type="module" module-name="killbill-util" scope="TEST" production-on-test="" />
-    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-util:test-jar:tests:0.3.6-SNAPSHOT" level="project" />
-    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing.commons:killbill-clock:test-jar:tests:0.1.7" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-util:test-jar:tests:0.5.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing.commons:killbill-clock:test-jar:tests:0.2.1" level="project" />
     <orderEntry type="library" scope="TEST" name="Maven: org.mockito:mockito-all:1.9.0" level="project" />
     <orderEntry type="library" scope="TEST" name="Maven: org.slf4j:slf4j-simple:1.7.5" level="project" />
     <orderEntry type="library" scope="TEST" name="Maven: org.testng:testng:6.3.1" level="project" />

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

diff --git a/catalog/pom.xml b/catalog/pom.xml
index 8f9798b..d1ff1c5 100644
--- a/catalog/pom.xml
+++ b/catalog/pom.xml
@@ -19,7 +19,7 @@
     <parent>
         <artifactId>killbill</artifactId>
         <groupId>com.ning.billing</groupId>
-        <version>0.3.6-SNAPSHOT</version>
+        <version>0.5.1-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <artifactId>killbill-catalog</artifactId>
diff --git a/entitlement/killbill-entitlement.iml b/entitlement/killbill-entitlement.iml
index 6c97505..74e5c95 100644
--- a/entitlement/killbill-entitlement.iml
+++ b/entitlement/killbill-entitlement.iml
@@ -12,6 +12,20 @@
     </content>
     <orderEntry type="inheritedJdk" />
     <orderEntry type="sourceFolder" forTests="false" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-payment:0.3.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-clock:0.1.7" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-queue:0.1.7" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-jdbi:0.1.7" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-notification:0.3.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-catalog:test-jar:tests:0.3.6-SNAPSHOT" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-util:test-jar:tests:0.3.6-SNAPSHOT" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing.commons:killbill-clock:test-jar:tests:0.1.7" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing.commons:killbill-queue:test-jar:tests:0.1.7" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing:killbill-api:0.6.0-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-payment:0.4.0-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-notification:0.4.0-SNAPSHOT" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-catalog:test-jar:tests:0.5.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-util:test-jar:tests:0.5.1-SNAPSHOT" level="project" />
     <orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-annotations:2.1.0" level="project" />
     <orderEntry type="library" scope="PROVIDED" name="Maven: com.google.code.findbugs:jsr305:1.3.9" level="project" />
     <orderEntry type="library" scope="PROVIDED" name="Maven: com.google.guava:guava:14.0.1" level="project" />
@@ -27,10 +41,10 @@
     <orderEntry type="module" module-name="killbill-account" />
     <orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-databind:2.1.0" level="project" />
     <orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-core:2.1.0" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing:killbill-api:0.3.3-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing:killbill-api:0.6.0-SNAPSHOT" level="project" />
     <orderEntry type="library" name="Maven: joda-time:joda-time:2.0" level="project" />
     <orderEntry type="module" module-name="killbill-internal-api" />
-    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-payment:0.3.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-payment:0.4.0-SNAPSHOT" level="project" />
     <orderEntry type="library" name="Maven: org.skife.config:config-magic:0.14" level="project" />
     <orderEntry type="library" name="Maven: org.slf4j:slf4j-api:1.7.5" level="project" />
     <orderEntry type="module" module-name="killbill-util" />
@@ -39,13 +53,14 @@
     <orderEntry type="library" name="Maven: com.jolbox:bonecp:0.7.1.RELEASE" level="project" />
     <orderEntry type="library" name="Maven: com.mchange:c3p0:0.9.2" level="project" />
     <orderEntry type="library" name="Maven: com.mchange:mchange-commons-java:0.2.3.3" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-clock:0.1.7" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-queue:0.1.7" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-jdbi:0.1.7" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-clock:0.2.1" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-locker:0.2.1" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-queue:0.2.1" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-jdbi:0.2.1" level="project" />
     <orderEntry type="library" name="Maven: org.jdbi:jdbi:2.39.1" level="project" />
     <orderEntry type="library" name="Maven: com.yammer.metrics:metrics-core:2.1.2" level="project" />
     <orderEntry type="library" name="Maven: org.weakref:jmxutils:1.12" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-notification:0.3.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-notification:0.4.0-SNAPSHOT" level="project" />
     <orderEntry type="library" name="Maven: com.samskivert:jmustache:1.5" level="project" />
     <orderEntry type="library" name="Maven: net.sf.ehcache:ehcache-core:2.6.2" level="project" />
     <orderEntry type="library" scope="RUNTIME" name="Maven: org.antlr:stringtemplate:3.2.1" level="project" />
@@ -53,14 +68,21 @@
     <orderEntry type="library" name="Maven: org.apache.commons:commons-email:1.2" level="project" />
     <orderEntry type="library" name="Maven: javax.mail:mail:1.4.1" level="project" />
     <orderEntry type="library" name="Maven: javax.activation:activation:1.1" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.shiro:shiro-core:1.2.2" level="project" />
+    <orderEntry type="library" name="Maven: commons-beanutils:commons-beanutils:1.8.3" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.shiro:shiro-ehcache:1.2.2" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.shiro:shiro-guice:1.2.2" level="project" />
+    <orderEntry type="library" scope="PROVIDED" name="Maven: com.google.inject.extensions:guice-multibindings:3.0" level="project" />
+    <orderEntry type="library" name="Maven: org.slf4j:jcl-over-slf4j:1.7.5" level="project" />
     <orderEntry type="module" module-name="killbill-catalog" scope="TEST" production-on-test="" />
-    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-catalog:test-jar:tests:0.3.6-SNAPSHOT" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-catalog:test-jar:tests:0.5.1-SNAPSHOT" level="project" />
     <orderEntry type="module" module-name="killbill-catalog" scope="TEST" />
     <orderEntry type="module" module-name="killbill-subscription" scope="TEST" />
     <orderEntry type="module" module-name="killbill-util" scope="TEST" production-on-test="" />
-    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-util:test-jar:tests:0.3.6-SNAPSHOT" level="project" />
-    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing.commons:killbill-clock:test-jar:tests:0.1.7" level="project" />
-    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing.commons:killbill-queue:test-jar:tests:0.1.7" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-util:test-jar:tests:0.5.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing.commons:killbill-clock:test-jar:tests:0.2.1" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing.commons:killbill-embeddeddb:0.2.1" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing.commons:killbill-queue:test-jar:tests:0.2.1" level="project" />
     <orderEntry type="library" scope="TEST" name="Maven: mysql:mysql-connector-mxj:5.0.12" level="project" />
     <orderEntry type="library" scope="TEST" name="Maven: mysql:mysql-connector-mxj-db-files:5.0.12" level="project" />
     <orderEntry type="library" scope="RUNTIME" name="Maven: mysql:mysql-connector-java:5.1.22" level="project" />
diff --git a/entitlement/pom.xml b/entitlement/pom.xml
index 0bc0275..0f93295 100644
--- a/entitlement/pom.xml
+++ b/entitlement/pom.xml
@@ -19,7 +19,7 @@
     <parent>
         <artifactId>killbill</artifactId>
         <groupId>com.ning.billing</groupId>
-        <version>0.3.6-SNAPSHOT</version>
+        <version>0.5.1-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <artifactId>killbill-entitlement</artifactId>
@@ -110,6 +110,11 @@
         </dependency>
         <dependency>
             <groupId>com.ning.billing.commons</groupId>
+            <artifactId>killbill-embeddeddb</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.ning.billing.commons</groupId>
             <artifactId>killbill-queue</artifactId>
         </dependency>
         <dependency>
diff --git a/invoice/killbill-invoice.iml b/invoice/killbill-invoice.iml
index 6290738..8673066 100644
--- a/invoice/killbill-invoice.iml
+++ b/invoice/killbill-invoice.iml
@@ -12,6 +12,14 @@
     </content>
     <orderEntry type="inheritedJdk" />
     <orderEntry type="sourceFolder" forTests="false" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-payment:0.3.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-clock:0.1.7" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-queue:0.1.7" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-jdbi:0.1.7" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-notification:0.3.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-catalog:test-jar:tests:0.3.6-SNAPSHOT" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-util:test-jar:tests:0.3.6-SNAPSHOT" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing.commons:killbill-clock:test-jar:tests:0.1.7" level="project" />
     <orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-annotations:2.1.0" level="project" />
     <orderEntry type="library" scope="PROVIDED" name="Maven: com.google.code.findbugs:jsr305:1.3.9" level="project" />
     <orderEntry type="library" scope="PROVIDED" name="Maven: com.google.guava:guava:14.0.1" level="project" />
@@ -24,11 +32,11 @@
     <orderEntry type="library" scope="TEST" name="Maven: org.hamcrest:hamcrest-core:1.1" level="project" />
     <orderEntry type="library" scope="TEST" name="Maven: cglib:cglib-nodep:2.2" level="project" />
     <orderEntry type="library" scope="TEST" name="Maven: org.objenesis:objenesis:1.2" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing:killbill-api:0.3.3-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing:killbill-api:0.6.0-SNAPSHOT" level="project" />
     <orderEntry type="library" name="Maven: joda-time:joda-time:2.0" level="project" />
     <orderEntry type="module" module-name="killbill-catalog" scope="TEST" />
     <orderEntry type="module" module-name="killbill-internal-api" />
-    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-payment:0.3.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-payment:0.4.0-SNAPSHOT" level="project" />
     <orderEntry type="library" name="Maven: org.skife.config:config-magic:0.14" level="project" />
     <orderEntry type="library" name="Maven: org.slf4j:slf4j-api:1.7.5" level="project" />
     <orderEntry type="module" module-name="killbill-util" />
@@ -39,13 +47,14 @@
     <orderEntry type="library" name="Maven: com.jolbox:bonecp:0.7.1.RELEASE" level="project" />
     <orderEntry type="library" name="Maven: com.mchange:c3p0:0.9.2" level="project" />
     <orderEntry type="library" name="Maven: com.mchange:mchange-commons-java:0.2.3.3" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-clock:0.1.7" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-queue:0.1.7" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-jdbi:0.1.7" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-clock:0.2.1" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-locker:0.2.1" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-queue:0.2.1" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-jdbi:0.2.1" level="project" />
     <orderEntry type="library" name="Maven: org.jdbi:jdbi:2.39.1" level="project" />
     <orderEntry type="library" name="Maven: com.yammer.metrics:metrics-core:2.1.2" level="project" />
     <orderEntry type="library" name="Maven: org.weakref:jmxutils:1.12" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-notification:0.3.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-notification:0.4.0-SNAPSHOT" level="project" />
     <orderEntry type="library" name="Maven: com.samskivert:jmustache:1.5" level="project" />
     <orderEntry type="library" name="Maven: net.sf.ehcache:ehcache-core:2.6.2" level="project" />
     <orderEntry type="library" scope="RUNTIME" name="Maven: org.antlr:stringtemplate:3.2.1" level="project" />
@@ -53,11 +62,18 @@
     <orderEntry type="library" name="Maven: org.apache.commons:commons-email:1.2" level="project" />
     <orderEntry type="library" name="Maven: javax.mail:mail:1.4.1" level="project" />
     <orderEntry type="library" name="Maven: javax.activation:activation:1.1" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.shiro:shiro-core:1.2.2" level="project" />
+    <orderEntry type="library" name="Maven: commons-beanutils:commons-beanutils:1.8.3" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.shiro:shiro-ehcache:1.2.2" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.shiro:shiro-guice:1.2.2" level="project" />
+    <orderEntry type="library" scope="PROVIDED" name="Maven: com.google.inject.extensions:guice-multibindings:3.0" level="project" />
+    <orderEntry type="library" name="Maven: org.slf4j:jcl-over-slf4j:1.7.5" level="project" />
     <orderEntry type="module" module-name="killbill-catalog" scope="TEST" production-on-test="" />
-    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-catalog:test-jar:tests:0.3.6-SNAPSHOT" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-catalog:test-jar:tests:0.5.1-SNAPSHOT" level="project" />
     <orderEntry type="module" module-name="killbill-util" scope="TEST" production-on-test="" />
-    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-util:test-jar:tests:0.3.6-SNAPSHOT" level="project" />
-    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing.commons:killbill-clock:test-jar:tests:0.1.7" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-util:test-jar:tests:0.5.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing.commons:killbill-clock:test-jar:tests:0.2.1" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing.commons:killbill-embeddeddb:0.2.1" level="project" />
     <orderEntry type="library" scope="TEST" name="Maven: mysql:mysql-connector-mxj:5.0.12" level="project" />
     <orderEntry type="library" scope="TEST" name="Maven: mysql:mysql-connector-mxj-db-files:5.0.12" level="project" />
     <orderEntry type="library" scope="RUNTIME" name="Maven: mysql:mysql-connector-java:5.1.22" level="project" />

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

diff --git a/invoice/pom.xml b/invoice/pom.xml
index 3fe0ba3..f67e327 100644
--- a/invoice/pom.xml
+++ b/invoice/pom.xml
@@ -19,7 +19,7 @@
     <parent>
         <artifactId>killbill</artifactId>
         <groupId>com.ning.billing</groupId>
-        <version>0.3.6-SNAPSHOT</version>
+        <version>0.5.1-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <artifactId>killbill-invoice</artifactId>
@@ -96,6 +96,11 @@
         </dependency>
         <dependency>
             <groupId>com.ning.billing.commons</groupId>
+            <artifactId>killbill-embeddeddb</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.ning.billing.commons</groupId>
             <artifactId>killbill-queue</artifactId>
         </dependency>
         <dependency>
diff --git a/invoice/src/main/java/com/ning/billing/invoice/InvoiceDispatcher.java b/invoice/src/main/java/com/ning/billing/invoice/InvoiceDispatcher.java
index 5ad6816..ff16d36 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/InvoiceDispatcher.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/InvoiceDispatcher.java
@@ -34,12 +34,16 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.ning.billing.ErrorCode;
+import com.ning.billing.ObjectType;
 import com.ning.billing.account.api.Account;
 import com.ning.billing.account.api.AccountApiException;
 import com.ning.billing.bus.api.PersistentBus;
 import com.ning.billing.bus.api.PersistentBus.EventBusException;
 import com.ning.billing.catalog.api.Currency;
-import com.ning.billing.subscription.api.user.SubscriptionBaseApiException;
+import com.ning.billing.clock.Clock;
+import com.ning.billing.commons.locker.GlobalLock;
+import com.ning.billing.commons.locker.GlobalLocker;
+import com.ning.billing.commons.locker.LockFailedException;
 import com.ning.billing.invoice.api.Invoice;
 import com.ning.billing.invoice.api.InvoiceApiException;
 import com.ning.billing.invoice.api.InvoiceItem;
@@ -57,20 +61,20 @@ import com.ning.billing.invoice.generator.InvoiceGenerator;
 import com.ning.billing.invoice.model.DefaultInvoice;
 import com.ning.billing.invoice.model.FixedPriceInvoiceItem;
 import com.ning.billing.invoice.model.RecurringInvoiceItem;
+import com.ning.billing.subscription.api.user.SubscriptionBaseApiException;
 import com.ning.billing.util.callcontext.InternalCallContext;
-import com.ning.billing.clock.Clock;
+import com.ning.billing.util.callcontext.InternalTenantContext;
+import com.ning.billing.util.callcontext.TenantContext;
+import com.ning.billing.util.dao.NonEntityDao;
 import com.ning.billing.util.events.BusInternalEvent;
 import com.ning.billing.util.events.EffectiveSubscriptionInternalEvent;
 import com.ning.billing.util.events.InvoiceAdjustmentInternalEvent;
 import com.ning.billing.util.events.InvoiceInternalEvent;
-import com.ning.billing.util.globallocker.GlobalLock;
-import com.ning.billing.util.globallocker.GlobalLocker;
-import com.ning.billing.util.globallocker.GlobalLocker.LockerType;
-import com.ning.billing.util.globallocker.LockFailedException;
+import com.ning.billing.util.globallocker.LockerType;
 import com.ning.billing.util.svcapi.account.AccountInternalApi;
-import com.ning.billing.util.svcapi.subscription.SubscriptionBaseInternalApi;
 import com.ning.billing.util.svcapi.junction.BillingEventSet;
 import com.ning.billing.util.svcapi.junction.BillingInternalApi;
+import com.ning.billing.util.svcapi.subscription.SubscriptionBaseInternalApi;
 import com.ning.billing.util.timezone.DateAndTimeZoneContext;
 
 import com.google.common.annotations.VisibleForTesting;
@@ -89,6 +93,7 @@ public class InvoiceDispatcher {
     private final AccountInternalApi accountApi;
     private final SubscriptionBaseInternalApi subscriptionApi;
     private final InvoiceDao invoiceDao;
+    private final NonEntityDao nonEntityDao;
     private final InvoiceNotifier invoiceNotifier;
     private final GlobalLocker locker;
     private final PersistentBus eventBus;
@@ -99,6 +104,7 @@ public class InvoiceDispatcher {
                              final BillingInternalApi billingApi,
                              final SubscriptionBaseInternalApi SubscriptionApi,
                              final InvoiceDao invoiceDao,
+                             final NonEntityDao nonEntityDao,
                              final InvoiceNotifier invoiceNotifier,
                              final GlobalLocker locker,
                              final PersistentBus eventBus,
@@ -108,6 +114,7 @@ public class InvoiceDispatcher {
         this.subscriptionApi = SubscriptionApi;
         this.accountApi = accountApi;
         this.invoiceDao = invoiceDao;
+        this.nonEntityDao = nonEntityDao;
         this.invoiceNotifier = invoiceNotifier;
         this.locker = locker;
         this.eventBus = eventBus;
@@ -139,7 +146,7 @@ public class InvoiceDispatcher {
                                   final boolean dryRun, final InternalCallContext context) throws InvoiceApiException {
         GlobalLock lock = null;
         try {
-            lock = locker.lockWithNumberOfTries(LockerType.ACCOUNT_FOR_INVOICE_PAYMENTS, accountId.toString(), NB_LOCK_TRY);
+            lock = locker.lockWithNumberOfTries(LockerType.ACCOUNT_FOR_INVOICE_PAYMENTS.toString(), accountId.toString(), NB_LOCK_TRY);
 
             return processAccountWithLock(accountId, targetDate, dryRun, context);
         } catch (LockFailedException e) {
@@ -192,7 +199,7 @@ public class InvoiceDispatcher {
                 }
             } else {
                 log.info("Generated invoice {} with {} items for accountId {} and targetDate {} (targetDateTime {})", new Object[]{invoice.getId(), invoice.getNumberOfItems(),
-                        accountId, targetDate, targetDateTime});
+                                                                                                                                   accountId, targetDate, targetDateTime});
                 if (!dryRun) {
 
                     // Extract the set of invoiceId for which we see items that don't belong to current generated invoice
@@ -254,7 +261,7 @@ public class InvoiceDispatcher {
             if (account.isNotifiedForInvoices() && invoice != null && !dryRun) {
                 // Need to re-hydrate the invoice object to get the invoice number (record id)
                 // API_FIX InvoiceNotifier public API?
-                invoiceNotifier.notify(account, new DefaultInvoice(invoiceDao.getById(invoice.getId(), context)), context.toTenantContext());
+                invoiceNotifier.notify(account, new DefaultInvoice(invoiceDao.getById(invoice.getId(), context)), buildTenantContext(context));
             }
 
             return invoice;
@@ -264,6 +271,9 @@ public class InvoiceDispatcher {
         }
     }
 
+    private TenantContext buildTenantContext(final InternalTenantContext context) {
+        return context.toTenantContext(nonEntityDao.retrieveIdFromObject(context.getTenantRecordId(), ObjectType.TENANT));
+    }
 
     @VisibleForTesting
     Map<UUID, DateTime> createNextFutureNotificationDate(final List<InvoiceItemModelDao> invoiceItems, final DateAndTimeZoneContext dateAndTimeZoneContext) {
@@ -273,6 +283,7 @@ public class InvoiceDispatcher {
         // at which we should be called back for next invoice.
         //
         for (final InvoiceItemModelDao item : invoiceItems) {
+
             if (item.getType() == InvoiceItemType.RECURRING) {
                 if ((item.getEndDate() != null) &&
                     (item.getAmount() == null ||
diff --git a/invoice/src/test/java/com/ning/billing/invoice/InvoiceTestSuiteNoDB.java b/invoice/src/test/java/com/ning/billing/invoice/InvoiceTestSuiteNoDB.java
index 9e4cfe7..179118a 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/InvoiceTestSuiteNoDB.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/InvoiceTestSuiteNoDB.java
@@ -27,6 +27,7 @@ import org.testng.annotations.BeforeMethod;
 
 import com.ning.billing.GuicyKillbillTestSuiteNoDB;
 import com.ning.billing.bus.api.PersistentBus;
+import com.ning.billing.commons.locker.GlobalLocker;
 import com.ning.billing.invoice.api.InvoiceMigrationApi;
 import com.ning.billing.invoice.api.InvoicePaymentApi;
 import com.ning.billing.invoice.api.InvoiceUserApi;
@@ -37,7 +38,6 @@ import com.ning.billing.util.api.TagUserApi;
 import com.ning.billing.util.cache.CacheControllerDispatcher;
 import com.ning.billing.util.callcontext.InternalCallContextFactory;
 import com.ning.billing.clock.Clock;
-import com.ning.billing.util.globallocker.GlobalLocker;
 import com.ning.billing.util.svcapi.account.AccountInternalApi;
 import com.ning.billing.util.svcapi.subscription.SubscriptionBaseInternalApi;
 import com.ning.billing.util.svcapi.invoice.InvoiceInternalApi;
diff --git a/invoice/src/test/java/com/ning/billing/invoice/InvoiceTestSuiteWithEmbeddedDB.java b/invoice/src/test/java/com/ning/billing/invoice/InvoiceTestSuiteWithEmbeddedDB.java
index 061c9b2..aff1faf 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/InvoiceTestSuiteWithEmbeddedDB.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/InvoiceTestSuiteWithEmbeddedDB.java
@@ -28,6 +28,7 @@ import org.testng.annotations.BeforeMethod;
 import com.ning.billing.GuicyKillbillTestSuiteWithEmbeddedDB;
 import com.ning.billing.bus.api.PersistentBus;
 import com.ning.billing.catalog.api.Currency;
+import com.ning.billing.commons.locker.GlobalLocker;
 import com.ning.billing.invoice.api.DefaultInvoiceService;
 import com.ning.billing.invoice.api.InvoiceMigrationApi;
 import com.ning.billing.invoice.api.InvoicePaymentApi;
@@ -42,7 +43,7 @@ import com.ning.billing.util.api.TagUserApi;
 import com.ning.billing.util.cache.CacheControllerDispatcher;
 import com.ning.billing.util.callcontext.InternalCallContextFactory;
 import com.ning.billing.clock.Clock;
-import com.ning.billing.util.globallocker.GlobalLocker;
+import com.ning.billing.util.dao.NonEntityDao;
 import com.ning.billing.util.svcapi.account.AccountInternalApi;
 import com.ning.billing.util.svcapi.subscription.SubscriptionBaseInternalApi;
 import com.ning.billing.util.svcapi.invoice.InvoiceInternalApi;
@@ -84,6 +85,8 @@ public abstract class InvoiceTestSuiteWithEmbeddedDB extends GuicyKillbillTestSu
     @Inject
     protected InvoiceDao invoiceDao;
     @Inject
+    protected NonEntityDao nonEntityDao;
+    @Inject
     protected TagUserApi tagUserApi;
     @Inject
     protected GlobalLocker locker;
diff --git a/invoice/src/test/java/com/ning/billing/invoice/TestInvoiceDispatcher.java b/invoice/src/test/java/com/ning/billing/invoice/TestInvoiceDispatcher.java
index 105904c..0342859 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/TestInvoiceDispatcher.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/TestInvoiceDispatcher.java
@@ -89,7 +89,7 @@ public class TestInvoiceDispatcher extends InvoiceTestSuiteWithEmbeddedDB {
 
         final InvoiceNotifier invoiceNotifier = new NullInvoiceNotifier();
         final InvoiceDispatcher dispatcher = new InvoiceDispatcher(generator, accountApi, billingApi, subscriptionApi, invoiceDao,
-                                                                   invoiceNotifier, locker, busService.getBus(),
+                                                                   nonEntityDao, invoiceNotifier, locker, busService.getBus(),
                                                                    clock);
 
         Invoice invoice = dispatcher.processAccount(accountId, target, true, internalCallContext);
@@ -143,7 +143,7 @@ public class TestInvoiceDispatcher extends InvoiceTestSuiteWithEmbeddedDB {
         Mockito.when(billingApi.getBillingEventsForAccountAndUpdateAccountBCD(Mockito.<UUID>any(), Mockito.<InternalCallContext>any())).thenReturn(events);
         final InvoiceNotifier invoiceNotifier = new NullInvoiceNotifier();
         final InvoiceDispatcher dispatcher = new InvoiceDispatcher(generator, accountApi, billingApi, subscriptionApi, invoiceDao,
-                                                                   invoiceNotifier, locker, busService.getBus(),
+                                                                   nonEntityDao, invoiceNotifier, locker, busService.getBus(),
                                                                    clock);
 
         final Invoice invoice = dispatcher.processAccount(account.getId(), new DateTime("2012-07-30T00:00:00.000Z"), false, internalCallContext);
@@ -203,7 +203,7 @@ public class TestInvoiceDispatcher extends InvoiceTestSuiteWithEmbeddedDB {
 
         final InvoiceNotifier invoiceNotifier = new NullInvoiceNotifier();
         final InvoiceDispatcher dispatcher = new InvoiceDispatcher(generator, accountApi, billingApi, subscriptionApi, invoiceDao,
-                                                                   invoiceNotifier, locker, busService.getBus(),
+                                                                   nonEntityDao, invoiceNotifier, locker, busService.getBus(),
                                                                    clock);
 
         final DateTime expectedBefore = clock.getUTCNow();
diff --git a/invoice/src/test/java/com/ning/billing/invoice/TestInvoiceHelper.java b/invoice/src/test/java/com/ning/billing/invoice/TestInvoiceHelper.java
index aac0a3d..76242b6 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/TestInvoiceHelper.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/TestInvoiceHelper.java
@@ -38,6 +38,7 @@ import com.ning.billing.catalog.api.BillingPeriod;
 import com.ning.billing.catalog.api.Currency;
 import com.ning.billing.catalog.api.Plan;
 import com.ning.billing.catalog.api.PlanPhase;
+import com.ning.billing.commons.locker.GlobalLocker;
 import com.ning.billing.subscription.api.SubscriptionBaseTransitionType;
 import com.ning.billing.subscription.api.SubscriptionBase;
 import com.ning.billing.invoice.api.Invoice;
@@ -59,8 +60,8 @@ import com.ning.billing.subscription.api.user.SubscriptionBaseApiException;
 import com.ning.billing.util.callcontext.InternalCallContext;
 import com.ning.billing.util.callcontext.InternalTenantContext;
 import com.ning.billing.clock.Clock;
+import com.ning.billing.util.dao.NonEntityDao;
 import com.ning.billing.util.entity.EntityPersistenceException;
-import com.ning.billing.util.globallocker.GlobalLocker;
 import com.ning.billing.util.svcapi.account.AccountInternalApi;
 import com.ning.billing.util.svcapi.subscription.SubscriptionBaseInternalApi;
 import com.ning.billing.util.svcapi.junction.BillingEvent;
@@ -132,9 +133,10 @@ public class TestInvoiceHelper {
     private final SubscriptionBaseInternalApi subscriptionApi;
     private final  BusService busService;
     private final  InvoiceDao invoiceDao;
-    private final  GlobalLocker locker;
+    private final GlobalLocker locker;
     private final  Clock clock;
     private final InternalCallContext internalCallContext;
+    private final NonEntityDao nonEntityDao;
 
     // Low level SqlDao used by the tests to directly insert rows
     private final InvoicePaymentSqlDao invoicePaymentSqlDao;
@@ -145,7 +147,7 @@ public class TestInvoiceHelper {
     @Inject
     public TestInvoiceHelper(final InvoiceGenerator generator, final IDBI dbi,
                              final BillingInternalApi billingApi, final AccountInternalApi accountApi, final SubscriptionBaseInternalApi subscriptionApi, final BusService busService,
-                             final InvoiceDao invoiceDao, final GlobalLocker locker, final Clock clock, final InternalCallContext internalCallContext) {
+                             final InvoiceDao invoiceDao, final GlobalLocker locker, final Clock clock, final NonEntityDao nonEntityDao, final InternalCallContext internalCallContext) {
         this.generator = generator;
         this.billingApi = billingApi;
         this.accountApi = accountApi;
@@ -154,6 +156,7 @@ public class TestInvoiceHelper {
         this.invoiceDao = invoiceDao;
         this.locker = locker;
         this.clock = clock;
+        this.nonEntityDao = nonEntityDao;
         this.internalCallContext = internalCallContext;
         this.invoiceItemSqlDao = dbi.onDemand(InvoiceItemSqlDao.class);
         this.invoicePaymentSqlDao = dbi.onDemand(InvoicePaymentSqlDao.class);
@@ -177,7 +180,7 @@ public class TestInvoiceHelper {
 
         final InvoiceNotifier invoiceNotifier = new NullInvoiceNotifier();
         final InvoiceDispatcher dispatcher = new InvoiceDispatcher(generator, accountApi, billingApi, subscriptionApi,
-                                                                   invoiceDao, invoiceNotifier, locker, busService.getBus(),
+                                                                   invoiceDao, nonEntityDao, invoiceNotifier, locker, busService.getBus(),
                                                                    clock);
 
         Invoice invoice = dispatcher.processAccount(account.getId(), targetDate, true, internalCallContext);
diff --git a/jaxrs/killbill-jaxrs.iml b/jaxrs/killbill-jaxrs.iml
index 89a28ef..9d9bcec 100644
--- a/jaxrs/killbill-jaxrs.iml
+++ b/jaxrs/killbill-jaxrs.iml
@@ -11,12 +11,19 @@
     </content>
     <orderEntry type="inheritedJdk" />
     <orderEntry type="sourceFolder" forTests="false" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-payment:0.3.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-clock:0.1.7" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-queue:0.1.7" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-jdbi:0.1.7" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-notification:0.3.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-util:test-jar:tests:0.3.6-SNAPSHOT" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing.commons:killbill-clock:test-jar:tests:0.1.7" level="project" />
     <orderEntry type="library" scope="PROVIDED" name="Maven: com.google.code.findbugs:jsr305:1.3.9" level="project" />
     <orderEntry type="library" scope="PROVIDED" name="Maven: com.google.guava:guava:14.0.1" level="project" />
     <orderEntry type="library" scope="PROVIDED" name="Maven: com.google.inject:guice:3.0" level="project" />
     <orderEntry type="library" scope="PROVIDED" name="Maven: javax.inject:javax.inject:1" level="project" />
     <orderEntry type="library" scope="PROVIDED" name="Maven: aopalliance:aopalliance:1.0" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing:killbill-api:0.3.3-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing:killbill-api:0.6.0-SNAPSHOT" level="project" />
     <orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-annotations:2.1.0" level="project" />
     <orderEntry type="library" name="Maven: joda-time:joda-time:2.0" level="project" />
     <orderEntry type="module" module-name="killbill-util" />
@@ -29,16 +36,17 @@
     <orderEntry type="library" name="Maven: com.mchange:c3p0:0.9.2" level="project" />
     <orderEntry type="library" name="Maven: com.mchange:mchange-commons-java:0.2.3.3" level="project" />
     <orderEntry type="module" module-name="killbill-internal-api" />
-    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-payment:0.3.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-payment:0.4.0-SNAPSHOT" level="project" />
     <orderEntry type="library" name="Maven: org.skife.config:config-magic:0.14" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-clock:0.1.7" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-queue:0.1.7" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-clock:0.2.1" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-locker:0.2.1" level="project" />
     <orderEntry type="library" scope="TEST" name="Maven: com.h2database:h2:1.3.158" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-jdbi:0.1.7" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-queue:0.2.1" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-jdbi:0.2.1" level="project" />
     <orderEntry type="library" name="Maven: org.jdbi:jdbi:2.39.1" level="project" />
     <orderEntry type="library" name="Maven: com.yammer.metrics:metrics-core:2.1.2" level="project" />
     <orderEntry type="library" name="Maven: org.weakref:jmxutils:1.12" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-notification:0.3.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-notification:0.4.0-SNAPSHOT" level="project" />
     <orderEntry type="library" name="Maven: com.samskivert:jmustache:1.5" level="project" />
     <orderEntry type="library" name="Maven: net.sf.ehcache:ehcache-core:2.6.2" level="project" />
     <orderEntry type="library" name="Maven: org.antlr:stringtemplate:3.2.1" level="project" />
@@ -46,9 +54,15 @@
     <orderEntry type="library" name="Maven: org.apache.commons:commons-email:1.2" level="project" />
     <orderEntry type="library" name="Maven: javax.mail:mail:1.4.1" level="project" />
     <orderEntry type="library" name="Maven: javax.activation:activation:1.1" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.shiro:shiro-core:1.2.2" level="project" />
+    <orderEntry type="library" name="Maven: commons-beanutils:commons-beanutils:1.8.3" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.shiro:shiro-ehcache:1.2.2" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.shiro:shiro-guice:1.2.2" level="project" />
+    <orderEntry type="library" scope="PROVIDED" name="Maven: com.google.inject.extensions:guice-multibindings:3.0" level="project" />
+    <orderEntry type="library" name="Maven: org.slf4j:jcl-over-slf4j:1.7.5" level="project" />
     <orderEntry type="module" module-name="killbill-util" scope="TEST" production-on-test="" />
-    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-util:test-jar:tests:0.3.6-SNAPSHOT" level="project" />
-    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing.commons:killbill-clock:test-jar:tests:0.1.7" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-util:test-jar:tests:0.5.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing.commons:killbill-clock:test-jar:tests:0.2.1" level="project" />
     <orderEntry type="library" scope="PROVIDED" name="Maven: javax.servlet:javax.servlet-api:3.0.1" level="project" />
     <orderEntry type="library" name="Maven: javax.ws.rs:jsr311-api:1.1.1" level="project" />
     <orderEntry type="library" scope="TEST" name="Maven: org.mockito:mockito-all:1.9.0" level="project" />

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

diff --git a/jaxrs/pom.xml b/jaxrs/pom.xml
index 390922b..02d85b7 100644
--- a/jaxrs/pom.xml
+++ b/jaxrs/pom.xml
@@ -19,7 +19,7 @@
     <parent>
         <artifactId>killbill</artifactId>
         <groupId>com.ning.billing</groupId>
-        <version>0.3.6-SNAPSHOT</version>
+        <version>0.5.1-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <artifactId>killbill-jaxrs</artifactId>
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/CatalogJsonSimple.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/CatalogJsonSimple.java
index d5520e6..11ed283 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/CatalogJsonSimple.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/CatalogJsonSimple.java
@@ -17,120 +17,150 @@
 package com.ning.billing.jaxrs.json;
 
 import java.math.BigDecimal;
-import java.util.Collection;
 import java.util.HashMap;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 
 import com.ning.billing.catalog.api.CatalogApiException;
+import com.ning.billing.catalog.api.CurrencyValueNull;
 import com.ning.billing.catalog.api.Plan;
 import com.ning.billing.catalog.api.PlanPhase;
 import com.ning.billing.catalog.api.Price;
 import com.ning.billing.catalog.api.Product;
 import com.ning.billing.catalog.api.StaticCatalog;
 
-import com.fasterxml.jackson.annotation.JsonAutoDetect;
 import com.fasterxml.jackson.annotation.JsonCreator;
 import com.fasterxml.jackson.annotation.JsonProperty;
 import com.google.common.base.Function;
-import com.google.common.collect.Collections2;
+import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Lists;
 
-@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)
 public class CatalogJsonSimple {
 
     private final String name;
-    private final ProductJson[] products;
+    private final List<ProductJson> products;
 
-    public CatalogJsonSimple(StaticCatalog catalog) throws CatalogApiException {
-        name = catalog.getCatalogName();
+    @JsonCreator
+    public CatalogJsonSimple(@JsonProperty("name") final String name,
+                             @JsonProperty("products") final List<ProductJson> products) {
+        this.name = name;
+        this.products = products;
+    }
 
-        Map<String, ProductJson> productMap = new HashMap<String, CatalogJsonSimple.ProductJson>();
 
-        Plan[] plans = catalog.getCurrentPlans();
-        for (Plan plan : plans) {
+    public CatalogJsonSimple(final StaticCatalog catalog) throws CatalogApiException {
+        name = catalog.getCatalogName();
 
-            Product product = plan.getProduct();
-            ProductJson jProduct = productMap.get(product.getName());
-            if (jProduct == null) {
-                jProduct = new ProductJson(product.getCategory().toString(),
-                                           product.getName(),
-                                           toProductNames(product.getIncluded()), toProductNames(product.getAvailable()));
-                productMap.put(product.getName(), jProduct);
+        final Plan[] plans = catalog.getCurrentPlans();
+        final Map<String, ProductJson> productMap = new HashMap<String, ProductJson>();
+        for (final Plan plan : plans) {
+            // Build the product associated with this plan
+            final Product product = plan.getProduct();
+            ProductJson productJson = productMap.get(product.getName());
+            if (productJson == null) {
+                productJson = new ProductJson(product.getCategory().toString(),
+                                              product.getName(),
+                                              toProductNames(product.getIncluded()),
+                                              toProductNames(product.getAvailable()));
+                productMap.put(product.getName(), productJson);
             }
 
-            int i = 0;
-            PhaseJson[] phases = new PhaseJson[plan.getAllPhases().length];
-            for (PlanPhase phase : plan.getAllPhases()) {
-
-                Map<String, BigDecimal> prices = new HashMap<String, BigDecimal>();
+            // Build the phases associated with this plan
+            final List<PhaseJson> phases = new LinkedList<PhaseJson>();
+            for (final PlanPhase phase : plan.getAllPhases()) {
+                final List<PriceJson> prices = new LinkedList<PriceJson>();
                 if (phase.getRecurringPrice() != null) {
-                    for (Price cur : phase.getRecurringPrice().getPrices()) {
-                        prices.put(cur.getCurrency().toString(), cur.getValue());
+                    for (final Price price : phase.getRecurringPrice().getPrices()) {
+                        prices.add(new PriceJson(price));
                     }
                 }
-                PhaseJson jPhase = new PhaseJson(phase.getPhaseType().toString(), prices);
-                phases[i++] = jPhase;
+
+                final PhaseJson phaseJson = new PhaseJson(phase.getPhaseType().toString(), prices);
+                phases.add(phaseJson);
             }
-            PlanJson jPlan = new PlanJson(plan.getName(), phases);
-            jProduct.addPlan(jPlan);
+
+            final PlanJson planJson = new PlanJson(plan.getName(), phases);
+            productJson.getPlans().add(planJson);
         }
-        products = productMap.values().toArray(new ProductJson[productMap.values().size()]);
+
+        products = ImmutableList.<ProductJson>copyOf(productMap.values());
     }
 
-    private Collection<String> toProductNames(Product[] in) {
-        return Collections2.transform(Lists.newArrayList(in), new Function<Product, String>() {
-            @Override
-            public String apply(Product input) {
-                return input.getName();
-            }
-        });
+    private List<String> toProductNames(final Product[] in) {
+        return Lists.transform(ImmutableList.<Product>copyOf(in),
+                               new Function<Product, String>() {
+                                   @Override
+                                   public String apply(final Product input) {
+                                       return input.getName();
+                                   }
+                               });
     }
 
-    @JsonCreator
-    public CatalogJsonSimple(@JsonProperty("name") final String name,
-                             @JsonProperty("products") ProductJson[] products) {
-        this.name = name;
-        this.products = products;
+    public List<ProductJson> getProducts() {
+        return products;
     }
 
+    @Override
+    public String toString() {
+        final StringBuilder sb = new StringBuilder("CatalogJsonSimple{");
+        sb.append("name='").append(name).append('\'');
+        sb.append(", products=").append(products);
+        sb.append('}');
+        return sb.toString();
+    }
 
-    public ProductJson[] getProducts() {
-        return products;
+    @Override
+    public boolean equals(final Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+
+        final CatalogJsonSimple that = (CatalogJsonSimple) o;
+
+        if (name != null ? !name.equals(that.name) : that.name != null) {
+            return false;
+        }
+        if (products != null ? !products.equals(that.products) : that.products != null) {
+            return false;
+        }
+
+        return true;
     }
 
+    @Override
+    public int hashCode() {
+        int result = name != null ? name.hashCode() : 0;
+        result = 31 * result + (products != null ? products.hashCode() : 0);
+        return result;
+    }
 
-    @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)
     public static class ProductJson {
 
         private final String type;
         private final String name;
-        private final String[] included;
-        private final String[] available;
         private final List<PlanJson> plans;
-
+        private final List<String> included;
+        private final List<String> available;
 
         @JsonCreator
-        public ProductJson(@JsonProperty("type") String type,
-                           @JsonProperty("name") String name,
-                           @JsonProperty("plans") List<PlanJson> plans,
-                           @JsonProperty("included") Collection<String> included,
-                           @JsonProperty("available") Collection<String> available) {
-            super();
+        public ProductJson(@JsonProperty("type") final String type,
+                           @JsonProperty("name") final String name,
+                           @JsonProperty("plans") final List<PlanJson> plans,
+                           @JsonProperty("included") final List<String> included,
+                           @JsonProperty("available") final List<String> available) {
             this.type = type;
             this.name = name;
-            this.included = included.toArray(new String[included.size()]);
-            this.available = available.toArray(new String[available.size()]);
             this.plans = plans;
+            this.included = included;
+            this.available = available;
         }
 
-        public ProductJson(String type, String name, Collection<String> included, Collection<String> available) {
-            this(type, name, new LinkedList<CatalogJsonSimple.PlanJson>(), included, available);
-        }
-
-        public void addPlan(PlanJson plan) {
-            plans.add(plan);
+        public ProductJson(final String type, final String name, final List<String> included, final List<String> available) {
+            this(type, name, new LinkedList<PlanJson>(), included, available);
         }
 
         public String getType() {
@@ -145,25 +175,75 @@ public class CatalogJsonSimple {
             return plans;
         }
 
-        public String[] getIncluded() {
+        public List<String> getIncluded() {
             return included;
         }
 
-        public String[] getAvailable() {
+        public List<String> getAvailable() {
             return available;
         }
+
+        @Override
+        public String toString() {
+            final StringBuilder sb = new StringBuilder("ProductJson{");
+            sb.append("type='").append(type).append('\'');
+            sb.append(", name='").append(name).append('\'');
+            sb.append(", plans=").append(plans);
+            sb.append(", included=").append(included);
+            sb.append(", available=").append(available);
+            sb.append('}');
+            return sb.toString();
+        }
+
+        @Override
+        public boolean equals(final Object o) {
+            if (this == o) {
+                return true;
+            }
+            if (o == null || getClass() != o.getClass()) {
+                return false;
+            }
+
+            final ProductJson that = (ProductJson) o;
+
+            if (available != null ? !available.equals(that.available) : that.available != null) {
+                return false;
+            }
+            if (included != null ? !included.equals(that.included) : that.included != null) {
+                return false;
+            }
+            if (name != null ? !name.equals(that.name) : that.name != null) {
+                return false;
+            }
+            if (plans != null ? !plans.equals(that.plans) : that.plans != null) {
+                return false;
+            }
+            if (type != null ? !type.equals(that.type) : that.type != null) {
+                return false;
+            }
+
+            return true;
+        }
+
+        @Override
+        public int hashCode() {
+            int result = type != null ? type.hashCode() : 0;
+            result = 31 * result + (name != null ? name.hashCode() : 0);
+            result = 31 * result + (plans != null ? plans.hashCode() : 0);
+            result = 31 * result + (included != null ? included.hashCode() : 0);
+            result = 31 * result + (available != null ? available.hashCode() : 0);
+            return result;
+        }
     }
 
-    @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)
     public static class PlanJson {
 
         private final String name;
-        private final PhaseJson[] phases;
+        private final List<PhaseJson> phases;
 
         @JsonCreator
-        public PlanJson(@JsonProperty("name") String name,
-                        @JsonProperty("phases") PhaseJson[] phases) {
-            super();
+        public PlanJson(@JsonProperty("name") final String name,
+                        @JsonProperty("phases") final List<PhaseJson> phases) {
             this.name = name;
             this.phases = phases;
         }
@@ -172,21 +252,56 @@ public class CatalogJsonSimple {
             return name;
         }
 
-        public PhaseJson[] getPhases() {
+        public List<PhaseJson> getPhases() {
             return phases;
         }
+
+        @Override
+        public String toString() {
+            final StringBuilder sb = new StringBuilder("PlanJson{");
+            sb.append("name='").append(name).append('\'');
+            sb.append(", phases=").append(phases);
+            sb.append('}');
+            return sb.toString();
+        }
+
+        @Override
+        public boolean equals(final Object o) {
+            if (this == o) {
+                return true;
+            }
+            if (o == null || getClass() != o.getClass()) {
+                return false;
+            }
+
+            final PlanJson planJson = (PlanJson) o;
+
+            if (name != null ? !name.equals(planJson.name) : planJson.name != null) {
+                return false;
+            }
+            if (phases != null ? !phases.equals(planJson.phases) : planJson.phases != null) {
+                return false;
+            }
+
+            return true;
+        }
+
+        @Override
+        public int hashCode() {
+            int result = name != null ? name.hashCode() : 0;
+            result = 31 * result + (phases != null ? phases.hashCode() : 0);
+            return result;
+        }
     }
 
-    @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)
     public static class PhaseJson {
 
         private final String type;
-        private final Map<String, BigDecimal> prices;
+        private final List<PriceJson> prices;
 
         @JsonCreator
-        public PhaseJson(@JsonProperty("type") String type,
-                         @JsonProperty("prices") Map<String, BigDecimal> prices) {
-            super();
+        public PhaseJson(@JsonProperty("type") final String type,
+                         @JsonProperty("prices") final List<PriceJson> prices) {
             this.type = type;
             this.prices = prices;
         }
@@ -194,9 +309,107 @@ public class CatalogJsonSimple {
         public String getType() {
             return type;
         }
-
-        public Map<String, BigDecimal> getPrices() {
+        public List<PriceJson> getPrices() {
             return prices;
         }
+
+        @Override
+        public String toString() {
+            final StringBuilder sb = new StringBuilder("PhaseJson{");
+            sb.append("type='").append(type).append('\'');
+            sb.append(", prices=").append(prices);
+            sb.append('}');
+            return sb.toString();
+        }
+
+        @Override
+        public boolean equals(final Object o) {
+            if (this == o) {
+                return true;
+            }
+            if (o == null || getClass() != o.getClass()) {
+                return false;
+            }
+
+            final PhaseJson phaseJson = (PhaseJson) o;
+
+            if (prices != null ? !prices.equals(phaseJson.prices) : phaseJson.prices != null) {
+                return false;
+            }
+            if (type != null ? !type.equals(phaseJson.type) : phaseJson.type != null) {
+                return false;
+            }
+
+            return true;
+        }
+
+        @Override
+        public int hashCode() {
+            int result = type != null ? type.hashCode() : 0;
+            result = 31 * result + (prices != null ? prices.hashCode() : 0);
+            return result;
+        }
+    }
+
+    public static class PriceJson {
+
+        private final String currency;
+        private final BigDecimal value;
+
+        @JsonCreator
+        public PriceJson(@JsonProperty("currency") final String currency,
+                         @JsonProperty("value") final BigDecimal value) {
+            this.currency = currency;
+            this.value = value;
+        }
+
+        public PriceJson(final Price price) throws CurrencyValueNull {
+            this(price.getCurrency().toString(), price.getValue());
+        }
+
+        public String getCurrency() {
+            return currency;
+        }
+
+        public BigDecimal getValue() {
+            return value;
+        }
+
+        @Override
+        public String toString() {
+            final StringBuilder sb = new StringBuilder("PriceJson{");
+            sb.append("currency='").append(currency).append('\'');
+            sb.append(", value=").append(value);
+            sb.append('}');
+            return sb.toString();
+        }
+
+        @Override
+        public boolean equals(final Object o) {
+            if (this == o) {
+                return true;
+            }
+            if (o == null || getClass() != o.getClass()) {
+                return false;
+            }
+
+            final PriceJson priceJson = (PriceJson) o;
+
+            if (currency != null ? !currency.equals(priceJson.currency) : priceJson.currency != null) {
+                return false;
+            }
+            if (value != null ? !value.equals(priceJson.value) : priceJson.value != null) {
+                return false;
+            }
+
+            return true;
+        }
+
+        @Override
+        public int hashCode() {
+            int result = currency != null ? currency.hashCode() : 0;
+            result = 31 * result + (value != null ? value.hashCode() : 0);
+            return result;
+        }
     }
 }
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/PaymentMethodJson.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/PaymentMethodJson.java
index ebc4c8a..5321232 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/PaymentMethodJson.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/PaymentMethodJson.java
@@ -123,6 +123,11 @@ public class PaymentMethodJson {
             public PaymentMethodPlugin getPluginDetail() {
                 return new PaymentMethodPlugin() {
                     @Override
+                    public UUID getKbPaymentMethodId() {
+                        return paymentMethodId == null ? null : UUID.fromString(paymentMethodId);
+                    }
+
+                    @Override
                     public boolean isDefaultPaymentMethod() {
                         // N/A
                         return false;
@@ -242,6 +247,58 @@ public class PaymentMethodJson {
         return pluginInfo;
     }
 
+    @Override
+    public String toString() {
+        final StringBuilder sb = new StringBuilder("PaymentMethodJson{");
+        sb.append("paymentMethodId='").append(paymentMethodId).append('\'');
+        sb.append(", accountId='").append(accountId).append('\'');
+        sb.append(", isDefault=").append(isDefault);
+        sb.append(", pluginName='").append(pluginName).append('\'');
+        sb.append(", pluginInfo=").append(pluginInfo);
+        sb.append('}');
+        return sb.toString();
+    }
+
+    @Override
+    public boolean equals(final Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+
+        final PaymentMethodJson that = (PaymentMethodJson) o;
+
+        if (accountId != null ? !accountId.equals(that.accountId) : that.accountId != null) {
+            return false;
+        }
+        if (isDefault != null ? !isDefault.equals(that.isDefault) : that.isDefault != null) {
+            return false;
+        }
+        if (paymentMethodId != null ? !paymentMethodId.equals(that.paymentMethodId) : that.paymentMethodId != null) {
+            return false;
+        }
+        if (pluginInfo != null ? !pluginInfo.equals(that.pluginInfo) : that.pluginInfo != null) {
+            return false;
+        }
+        if (pluginName != null ? !pluginName.equals(that.pluginName) : that.pluginName != null) {
+            return false;
+        }
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = paymentMethodId != null ? paymentMethodId.hashCode() : 0;
+        result = 31 * result + (accountId != null ? accountId.hashCode() : 0);
+        result = 31 * result + (isDefault != null ? isDefault.hashCode() : 0);
+        result = 31 * result + (pluginName != null ? pluginName.hashCode() : 0);
+        result = 31 * result + (pluginInfo != null ? pluginInfo.hashCode() : 0);
+        return result;
+    }
+
     public static class PaymentMethodPluginDetailJson {
 
         private final String externalPaymentId;
@@ -352,6 +409,108 @@ public class PaymentMethodJson {
         public List<PaymentMethodProperties> getProperties() {
             return properties;
         }
+
+        @Override
+        public String toString() {
+            final StringBuilder sb = new StringBuilder("PaymentMethodPluginDetailJson{");
+            sb.append("externalPaymentId='").append(externalPaymentId).append('\'');
+            sb.append(", isDefaultPaymentMethod=").append(isDefaultPaymentMethod);
+            sb.append(", type='").append(type).append('\'');
+            sb.append(", ccName='").append(ccName).append('\'');
+            sb.append(", ccType='").append(ccType).append('\'');
+            sb.append(", ccExpirationMonth='").append(ccExpirationMonth).append('\'');
+            sb.append(", ccExpirationYear='").append(ccExpirationYear).append('\'');
+            sb.append(", ccLast4='").append(ccLast4).append('\'');
+            sb.append(", address1='").append(address1).append('\'');
+            sb.append(", address2='").append(address2).append('\'');
+            sb.append(", city='").append(city).append('\'');
+            sb.append(", state='").append(state).append('\'');
+            sb.append(", zip='").append(zip).append('\'');
+            sb.append(", country='").append(country).append('\'');
+            sb.append(", properties=").append(properties);
+            sb.append('}');
+            return sb.toString();
+        }
+
+        @Override
+        public boolean equals(final Object o) {
+            if (this == o) {
+                return true;
+            }
+            if (o == null || getClass() != o.getClass()) {
+                return false;
+            }
+
+            final PaymentMethodPluginDetailJson that = (PaymentMethodPluginDetailJson) o;
+
+            if (address1 != null ? !address1.equals(that.address1) : that.address1 != null) {
+                return false;
+            }
+            if (address2 != null ? !address2.equals(that.address2) : that.address2 != null) {
+                return false;
+            }
+            if (ccExpirationMonth != null ? !ccExpirationMonth.equals(that.ccExpirationMonth) : that.ccExpirationMonth != null) {
+                return false;
+            }
+            if (ccExpirationYear != null ? !ccExpirationYear.equals(that.ccExpirationYear) : that.ccExpirationYear != null) {
+                return false;
+            }
+            if (ccLast4 != null ? !ccLast4.equals(that.ccLast4) : that.ccLast4 != null) {
+                return false;
+            }
+            if (ccName != null ? !ccName.equals(that.ccName) : that.ccName != null) {
+                return false;
+            }
+            if (ccType != null ? !ccType.equals(that.ccType) : that.ccType != null) {
+                return false;
+            }
+            if (city != null ? !city.equals(that.city) : that.city != null) {
+                return false;
+            }
+            if (country != null ? !country.equals(that.country) : that.country != null) {
+                return false;
+            }
+            if (externalPaymentId != null ? !externalPaymentId.equals(that.externalPaymentId) : that.externalPaymentId != null) {
+                return false;
+            }
+            if (isDefaultPaymentMethod != null ? !isDefaultPaymentMethod.equals(that.isDefaultPaymentMethod) : that.isDefaultPaymentMethod != null) {
+                return false;
+            }
+            if (properties != null ? !properties.equals(that.properties) : that.properties != null) {
+                return false;
+            }
+            if (state != null ? !state.equals(that.state) : that.state != null) {
+                return false;
+            }
+            if (type != null ? !type.equals(that.type) : that.type != null) {
+                return false;
+            }
+            if (zip != null ? !zip.equals(that.zip) : that.zip != null) {
+                return false;
+            }
+
+            return true;
+        }
+
+        @Override
+        public int hashCode() {
+            int result = externalPaymentId != null ? externalPaymentId.hashCode() : 0;
+            result = 31 * result + (isDefaultPaymentMethod != null ? isDefaultPaymentMethod.hashCode() : 0);
+            result = 31 * result + (type != null ? type.hashCode() : 0);
+            result = 31 * result + (ccName != null ? ccName.hashCode() : 0);
+            result = 31 * result + (ccType != null ? ccType.hashCode() : 0);
+            result = 31 * result + (ccExpirationMonth != null ? ccExpirationMonth.hashCode() : 0);
+            result = 31 * result + (ccExpirationYear != null ? ccExpirationYear.hashCode() : 0);
+            result = 31 * result + (ccLast4 != null ? ccLast4.hashCode() : 0);
+            result = 31 * result + (address1 != null ? address1.hashCode() : 0);
+            result = 31 * result + (address2 != null ? address2.hashCode() : 0);
+            result = 31 * result + (city != null ? city.hashCode() : 0);
+            result = 31 * result + (state != null ? state.hashCode() : 0);
+            result = 31 * result + (zip != null ? zip.hashCode() : 0);
+            result = 31 * result + (country != null ? country.hashCode() : 0);
+            result = 31 * result + (properties != null ? properties.hashCode() : 0);
+            return result;
+        }
     }
 
     public static final class PaymentMethodProperties {
@@ -381,5 +540,47 @@ public class PaymentMethodJson {
         public Boolean getIsUpdatable() {
             return isUpdatable;
         }
+
+        @Override
+        public String toString() {
+            final StringBuilder sb = new StringBuilder("PaymentMethodProperties{");
+            sb.append("key='").append(key).append('\'');
+            sb.append(", value='").append(value).append('\'');
+            sb.append(", isUpdatable=").append(isUpdatable);
+            sb.append('}');
+            return sb.toString();
+        }
+
+        @Override
+        public boolean equals(final Object o) {
+            if (this == o) {
+                return true;
+            }
+            if (o == null || getClass() != o.getClass()) {
+                return false;
+            }
+
+            final PaymentMethodProperties that = (PaymentMethodProperties) o;
+
+            if (isUpdatable != null ? !isUpdatable.equals(that.isUpdatable) : that.isUpdatable != null) {
+                return false;
+            }
+            if (key != null ? !key.equals(that.key) : that.key != null) {
+                return false;
+            }
+            if (value != null ? !value.equals(that.value) : that.value != null) {
+                return false;
+            }
+
+            return true;
+        }
+
+        @Override
+        public int hashCode() {
+            int result = key != null ? key.hashCode() : 0;
+            result = 31 * result + (value != null ? value.hashCode() : 0);
+            result = 31 * result + (isUpdatable != null ? isUpdatable.hashCode() : 0);
+            return result;
+        }
     }
 }
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/PlanDetailJson.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/PlanDetailJson.java
index 71bbd64..74ec110 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/PlanDetailJson.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/PlanDetailJson.java
@@ -16,9 +16,21 @@
 
 package com.ning.billing.jaxrs.json;
 
+import java.math.BigDecimal;
+import java.util.List;
+
 import com.ning.billing.catalog.api.BillingPeriod;
-import com.ning.billing.catalog.api.InternationalPrice;
+import com.ning.billing.catalog.api.CurrencyValueNull;
 import com.ning.billing.catalog.api.Listing;
+import com.ning.billing.catalog.api.Plan;
+import com.ning.billing.catalog.api.Price;
+import com.ning.billing.jaxrs.json.CatalogJsonSimple.PriceJson;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.google.common.base.Function;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
 
 import com.fasterxml.jackson.annotation.JsonCreator;
 import com.fasterxml.jackson.annotation.JsonProperty;
@@ -29,14 +41,14 @@ public class PlanDetailJson {
     final String planName;
     final BillingPeriod billingPeriod;
     final String priceListName;
-    final InternationalPrice finalPhasePrice;
+    final List<PriceJson> finalPhasePrice;
 
     @JsonCreator
     public PlanDetailJson(@JsonProperty("product") final String productName,
                           @JsonProperty("plan") final String planName,
                           @JsonProperty("final_phase_billing_period") final BillingPeriod billingPeriod,
                           @JsonProperty("priceList") final String priceListName,
-                          @JsonProperty("final_phase_recurring_price") final InternationalPrice finalPhasePrice) {
+                          @JsonProperty("final_phase_recurring_price") final List<PriceJson> finalPhasePrice) {
         this.productName = productName;
         this.planName = planName;
         this.billingPeriod = billingPeriod;
@@ -45,8 +57,33 @@ public class PlanDetailJson {
     }
 
     public PlanDetailJson(final Listing listing) {
-        this(listing.getPlan().getProduct().getName(), listing.getPlan().getName(), listing.getPlan().getBillingPeriod(),
-             listing.getPriceList().getName(), listing.getPlan().getFinalPhase().getRecurringPrice());
+        final Plan plan = listing.getPlan();
+        if (plan == null) {
+            this.productName = null;
+            this.planName = null;
+            this.billingPeriod = null;
+            this.finalPhasePrice = ImmutableList.<PriceJson>of();
+        } else {
+            this.productName = plan.getProduct() == null ? null : plan.getProduct().getName();
+            this.planName = plan.getName();
+            this.billingPeriod = plan.getBillingPeriod();
+            if (plan.getFinalPhase() == null || plan.getFinalPhase().getRecurringPrice() == null || plan.getFinalPhase().getRecurringPrice().getPrices() == null) {
+                this.finalPhasePrice = ImmutableList.<PriceJson>of();
+            } else {
+                this.finalPhasePrice = Lists.transform(ImmutableList.<Price>copyOf(plan.getFinalPhase().getRecurringPrice().getPrices()),
+                                                       new Function<Price, PriceJson>() {
+                                                           @Override
+                                                           public PriceJson apply(final Price price) {
+                                                               try {
+                                                                   return new PriceJson(price);
+                                                               } catch (CurrencyValueNull e) {
+                                                                   return new PriceJson(price.getCurrency().toString(), BigDecimal.ZERO);
+                                                               }
+                                                           }
+                                                       });
+            }
+        }
+        this.priceListName = listing.getPriceList() == null ? null : listing.getPriceList().getName();
     }
 
     public String getProductName() {
@@ -65,11 +102,23 @@ public class PlanDetailJson {
         return priceListName;
     }
 
-    public InternationalPrice getFinalPhasePrice() {
+    public List<PriceJson> getFinalPhasePrice() {
         return finalPhasePrice;
     }
 
     @Override
+    public String toString() {
+        final StringBuilder sb = new StringBuilder("PlanDetailJson{");
+        sb.append("productName='").append(productName).append('\'');
+        sb.append(", planName='").append(planName).append('\'');
+        sb.append(", billingPeriod=").append(billingPeriod);
+        sb.append(", priceListName='").append(priceListName).append('\'');
+        sb.append(", finalPhasePrice=").append(finalPhasePrice);
+        sb.append('}');
+        return sb.toString();
+    }
+
+    @Override
     public boolean equals(final Object o) {
         if (this == o) {
             return true;
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/mappers/ExceptionMapperBase.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/mappers/ExceptionMapperBase.java
index fd2abb3..2c82fa6 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/mappers/ExceptionMapperBase.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/mappers/ExceptionMapperBase.java
@@ -73,6 +73,19 @@ public abstract class ExceptionMapperBase {
                        .build();
     }
 
+    protected Response buildAuthorizationErrorResponse(final Exception e, final UriInfo uriInfo) {
+        // Log the full stacktrace
+        log.warn("Authorization error", e);
+        return buildAuthorizationErrorResponse(exceptionToString(e), uriInfo);
+    }
+
+    private Response buildAuthorizationErrorResponse(final String error, final UriInfo uriInfo) {
+        return Response.status(Status.UNAUTHORIZED) // TODO Forbidden?
+                       .entity(error)
+                       .type(MediaType.TEXT_PLAIN_TYPE)
+                       .build();
+    }
+
     protected Response buildInternalErrorResponse(final Exception e, final UriInfo uriInfo) {
         // Log the full stacktrace
         log.warn("Internal error", e);
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/mappers/ShiroExceptionMapper.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/mappers/ShiroExceptionMapper.java
new file mode 100644
index 0000000..4558b1c
--- /dev/null
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/mappers/ShiroExceptionMapper.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2010-2013 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.mappers;
+
+import javax.inject.Singleton;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+import javax.ws.rs.ext.ExceptionMapper;
+import javax.ws.rs.ext.Provider;
+
+import org.apache.shiro.ShiroException;
+
+@Singleton
+@Provider
+public class ShiroExceptionMapper extends ExceptionMapperBase implements ExceptionMapper<ShiroException> {
+
+    private final UriInfo uriInfo;
+
+    public ShiroExceptionMapper(@Context final UriInfo uriInfo) {
+        this.uriInfo = uriInfo;
+    }
+
+    @Override
+    public Response toResponse(final ShiroException exception) {
+        return buildAuthorizationErrorResponse(exception, uriInfo);
+    }
+}
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 09ca97f..eebe22b 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
@@ -23,6 +23,7 @@ import java.util.LinkedList;
 import java.util.List;
 import java.util.UUID;
 
+import javax.annotation.Nullable;
 import javax.servlet.http.HttpServletRequest;
 import javax.ws.rs.Consumes;
 import javax.ws.rs.DELETE;
@@ -96,6 +97,7 @@ import com.ning.billing.util.tag.ControlTagType;
 import com.google.common.base.Function;
 import com.google.common.collect.ArrayListMultimap;
 import com.google.common.collect.Collections2;
+import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Multimap;
 import com.google.inject.Inject;
 import com.google.inject.Singleton;
@@ -147,7 +149,26 @@ public class AccountResource extends JaxRsResourceBase {
                                @javax.ws.rs.core.Context final HttpServletRequest request) throws AccountApiException {
         final TenantContext tenantContext = context.createContext(request);
         final Account account = accountUserApi.getAccountById(UUID.fromString(accountId), tenantContext);
-        return getAccount(account, accountWithBalance, accountWithBalanceAndCBA, tenantContext);
+        final AccountJson accountJson = getAccount(account, accountWithBalance, accountWithBalanceAndCBA, tenantContext);
+        return Response.status(Status.OK).entity(accountJson).build();
+    }
+
+    @GET
+    @Path("/" + SEARCH + "/{searchKey:" + ANYTHING_PATTERN + "}")
+    @Produces(APPLICATION_JSON)
+    public Response searchAccounts(@PathParam("searchKey") final String searchKey,
+                                   @QueryParam(QUERY_ACCOUNT_WITH_BALANCE) @DefaultValue("false") final Boolean accountWithBalance,
+                                   @QueryParam(QUERY_ACCOUNT_WITH_BALANCE_AND_CBA) @DefaultValue("false") final Boolean accountWithBalanceAndCBA,
+                                   @javax.ws.rs.core.Context final HttpServletRequest request) throws AccountApiException {
+        final TenantContext tenantContext = context.createContext(request);
+        final List<Account> accounts = accountUserApi.searchAccounts(searchKey, tenantContext);
+        final List<AccountJson> accountsJson = ImmutableList.<AccountJson>copyOf(Collections2.transform(accounts, new Function<Account, AccountJson>() {
+            @Override
+            public AccountJson apply(final Account account) {
+                return getAccount(account, accountWithBalance, accountWithBalanceAndCBA, tenantContext);
+            }
+        }));
+        return Response.status(Status.OK).entity(accountsJson).build();
     }
 
 
@@ -186,22 +207,22 @@ public class AccountResource extends JaxRsResourceBase {
                                     @javax.ws.rs.core.Context final HttpServletRequest request) throws AccountApiException {
         final TenantContext tenantContext = context.createContext(request);
         final Account account = accountUserApi.getAccountByKey(externalKey, tenantContext);
-        return getAccount(account, accountWithBalance, accountWithBalanceAndCBA, tenantContext);
+        final AccountJson accountJson = getAccount(account, accountWithBalance, accountWithBalanceAndCBA, tenantContext);
+        return Response.status(Status.OK).entity(accountJson).build();
     }
 
-    private Response getAccount(final Account account, final Boolean accountWithBalance, final Boolean accountWithBalanceAndCBA, final TenantContext tenantContext) {
+    private AccountJson getAccount(final Account account, final Boolean accountWithBalance, final Boolean accountWithBalanceAndCBA, final TenantContext tenantContext) {
         final AccountJson json;
         if (accountWithBalanceAndCBA) {
             final BigDecimal accountBalance = invoiceApi.getAccountBalance(account.getId(), tenantContext);
             final BigDecimal accountCBA = invoiceApi.getAccountCBA(account.getId(), tenantContext);
-            json = new AccountJsonWithBalanceAndCBA(account, accountBalance, accountCBA);
+            return new AccountJsonWithBalanceAndCBA(account, accountBalance, accountCBA);
         } else if (accountWithBalance) {
             final BigDecimal accountBalance = invoiceApi.getAccountBalance(account.getId(), tenantContext);
-            json = new AccountJsonWithBalance(account, accountBalance);
+            return new AccountJsonWithBalance(account, accountBalance);
         } else {
-            json = new AccountJson(account);
+            return new AccountJson(account);
         }
-        return Response.status(Status.OK).entity(json).build();
     }
 
     @POST
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 0f18465..c3648e6 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
@@ -153,6 +153,21 @@ public class InvoiceResource extends JaxRsResourceBase {
     }
 
     @GET
+    @Path("/{invoiceNumber:" + NUMBER_PATTERN + "}/")
+    @Produces(APPLICATION_JSON)
+    public Response getInvoiceByNumber(@PathParam("invoiceNumber") final Integer invoiceNumber,
+                                       @QueryParam(QUERY_INVOICE_WITH_ITEMS) @DefaultValue("false") final boolean withItems,
+                                       @javax.ws.rs.core.Context final HttpServletRequest request) throws InvoiceApiException {
+        final Invoice invoice = invoiceApi.getInvoiceByNumber(invoiceNumber, context.createContext(request));
+        if (invoice == null) {
+            throw new InvoiceApiException(ErrorCode.INVOICE_NOT_FOUND, invoiceNumber);
+        } else {
+            final InvoiceJsonSimple json = withItems ? new InvoiceJsonWithItems(invoice) : new InvoiceJsonSimple(invoice);
+            return Response.status(Status.OK).entity(json).build();
+        }
+    }
+
+    @GET
     @Path("/{invoiceId:" + UUID_PATTERN + "}/html")
     @Produces(TEXT_HTML)
     public Response getInvoiceAsHTML(@PathParam("invoiceId") final String invoiceId,
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/JaxrsResource.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/JaxrsResource.java
index 87e1ed0..b4e021d 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/JaxrsResource.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/JaxrsResource.java
@@ -26,6 +26,13 @@ public interface JaxrsResource {
 
     public static final String TIMELINE = "timeline";
     public static final String REGISTER_NOTIFICATION_CALLBACK = "registerNotificationCallback";
+    public static final String SEARCH = "search";
+
+    /*
+     * Multi-Tenancy headers
+     */
+    public static String HDR_API_KEY = "X-Killbill-ApiKey";
+    public static String HDR_API_SECRET = "X-Killbill-ApiSecret";
 
     /*
      * Metadata Additional headers
@@ -39,6 +46,8 @@ public interface JaxrsResource {
      */
     public static String STRING_PATTERN = "[\\w-]+";
     public static String UUID_PATTERN = "\\w+-\\w+-\\w+-\\w+-\\w+";
+    public static String NUMBER_PATTERN = "[0-9]+";
+    public static String ANYTHING_PATTERN = ".*";
 
     /*
      * Query parameters
@@ -65,6 +74,7 @@ public interface JaxrsResource {
     public static final String QUERY_TAGS = "tagList";
     public static final String QUERY_CUSTOM_FIELDS = "customFieldList";
 
+    public static final String QUERY_PAYMENT_METHOD_PLUGIN_NAME = "pluginName";
     public static final String QUERY_PAYMENT_METHOD_PLUGIN_INFO = "withPluginInfo";
     public static final String QUERY_PAYMENT_METHOD_IS_DEFAULT = "isDefault";
 
@@ -86,6 +96,9 @@ public interface JaxrsResource {
     public static final String BUNDLES = "bundles";
     public static final String BUNDLES_PATH = PREFIX + "/" + BUNDLES;
 
+    public static final String SECURITY = "security";
+    public static final String SECURITY_PATH = PREFIX + "/" + SECURITY;
+
     public static final String SUBSCRIPTIONS = "subscriptions";
     public static final String SUBSCRIPTIONS_PATH = PREFIX + "/" + SUBSCRIPTIONS;
 
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/PaymentMethodResource.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/PaymentMethodResource.java
index 5b32b46..1218a08 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/PaymentMethodResource.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/PaymentMethodResource.java
@@ -16,6 +16,9 @@
 
 package com.ning.billing.jaxrs.resources;
 
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 import java.util.UUID;
 
 import javax.servlet.http.HttpServletRequest;
@@ -47,6 +50,9 @@ import com.ning.billing.util.api.TagUserApi;
 import com.ning.billing.util.callcontext.CallContext;
 import com.ning.billing.util.callcontext.TenantContext;
 
+import com.google.common.base.Function;
+import com.google.common.base.Strings;
+import com.google.common.collect.Lists;
 import com.google.inject.Inject;
 import com.google.inject.Singleton;
 
@@ -86,6 +92,40 @@ public class PaymentMethodResource extends JaxRsResourceBase {
         return Response.status(Status.OK).entity(json).build();
     }
 
+    @GET
+    @Path("/" + SEARCH + "/{searchKey:" + ANYTHING_PATTERN + "}")
+    @Produces(APPLICATION_JSON)
+    public Response searchPaymentMethods(@PathParam("searchKey") final String searchKey,
+                                         @QueryParam(QUERY_PAYMENT_METHOD_PLUGIN_NAME) final String pluginName,
+                                         @javax.ws.rs.core.Context final HttpServletRequest request) throws PaymentApiException, AccountApiException {
+        final TenantContext tenantContext = context.createContext(request);
+
+        // Search the plugin(s)
+        final List<PaymentMethod> paymentMethods;
+        if (Strings.isNullOrEmpty(pluginName)) {
+            paymentMethods = paymentApi.searchPaymentMethods(searchKey, tenantContext);
+        } else {
+            paymentMethods = paymentApi.searchPaymentMethods(searchKey, pluginName, tenantContext);
+        }
+
+        // Lookup the associated account(s)
+        final Map<UUID, Account> accounts = new HashMap<UUID, Account>();
+        for (final PaymentMethod paymentMethod : paymentMethods) {
+            if (accounts.get(paymentMethod.getAccountId()) == null) {
+                final Account account = accountUserApi.getAccountById(paymentMethod.getAccountId(), tenantContext);
+                accounts.put(paymentMethod.getAccountId(), account);
+            }
+        }
+
+        final List<PaymentMethodJson> json = Lists.transform(paymentMethods, new Function<PaymentMethod, PaymentMethodJson>() {
+            @Override
+            public PaymentMethodJson apply(final PaymentMethod paymentMethod) {
+                return PaymentMethodJson.toPaymentMethodJson(accounts.get(paymentMethod.getAccountId()), paymentMethod);
+            }
+        });
+        return Response.status(Status.OK).entity(json).build();
+    }
+
     @DELETE
     @Produces(APPLICATION_JSON)
     @Path("/{paymentMethodId:" + UUID_PATTERN + "}")
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/SecurityResource.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/SecurityResource.java
new file mode 100644
index 0000000..133d632
--- /dev/null
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/SecurityResource.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2010-2013 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 java.util.List;
+import java.util.Set;
+
+import javax.inject.Singleton;
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+
+import com.ning.billing.account.api.AccountUserApi;
+import com.ning.billing.clock.Clock;
+import com.ning.billing.jaxrs.util.Context;
+import com.ning.billing.jaxrs.util.JaxrsUriBuilder;
+import com.ning.billing.security.Permission;
+import com.ning.billing.security.api.SecurityApi;
+import com.ning.billing.util.api.AuditUserApi;
+import com.ning.billing.util.api.CustomFieldUserApi;
+import com.ning.billing.util.api.TagUserApi;
+
+import com.google.common.base.Functions;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+import com.google.inject.Inject;
+
+import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
+
+@Singleton
+@Path(JaxrsResource.SECURITY_PATH)
+public class SecurityResource extends JaxRsResourceBase {
+
+    private final SecurityApi securityApi;
+
+    @Inject
+    public SecurityResource(final SecurityApi securityApi,
+                            final JaxrsUriBuilder uriBuilder,
+                            final TagUserApi tagUserApi,
+                            final CustomFieldUserApi customFieldUserApi,
+                            final AuditUserApi auditUserApi,
+                            final AccountUserApi accountUserApi,
+                            final Clock clock,
+                            final Context context) {
+        super(uriBuilder, tagUserApi, customFieldUserApi, auditUserApi, accountUserApi, clock, context);
+        this.securityApi = securityApi;
+    }
+
+    @GET
+    @Path("/permissions")
+    @Produces(APPLICATION_JSON)
+    public Response getCurrentUserPermissions(@javax.ws.rs.core.Context final HttpServletRequest request)  {
+        final Set<Permission> permissions = securityApi.getCurrentUserPermissions(context.createContext(request));
+        final List<String> json = ImmutableList.<String>copyOf(Iterables.<Permission, String>transform(permissions, Functions.toStringFunction()));
+        return Response.status(Status.OK).entity(json).build();
+    }
+
+}
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 18b95b7..6776382 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
@@ -67,6 +67,7 @@ public class Context {
     }
 
     private Tenant getTenantFromRequest(final ServletRequest request) {
+        // See com.ning.billing.server.security.TenantFilter
         final Object tenantObject = request.getAttribute("killbill_tenant");
         if (tenantObject == null) {
             return null;
diff --git a/jaxrs/src/test/java/com/ning/billing/jaxrs/json/TestPlanDetailJason.java b/jaxrs/src/test/java/com/ning/billing/jaxrs/json/TestPlanDetailJason.java
index 003b541..b273e71 100644
--- a/jaxrs/src/test/java/com/ning/billing/jaxrs/json/TestPlanDetailJason.java
+++ b/jaxrs/src/test/java/com/ning/billing/jaxrs/json/TestPlanDetailJason.java
@@ -84,6 +84,6 @@ public class TestPlanDetailJason extends JaxrsTestSuiteNoDB {
         Assert.assertEquals(planDetailJason.getPlanName(), plan.getName());
         Assert.assertEquals(planDetailJason.getBillingPeriod(), plan.getBillingPeriod());
         Assert.assertEquals(planDetailJason.getPriceListName(), priceList.getName());
-        Assert.assertEquals(planDetailJason.getFinalPhasePrice(), plan.getFinalPhase().getRecurringPrice());
+        Assert.assertEquals(planDetailJason.getFinalPhasePrice().size(), 0);
     }
 }
diff --git a/junction/killbill-junction.iml b/junction/killbill-junction.iml
index 85454cf..1cf83d7 100644
--- a/junction/killbill-junction.iml
+++ b/junction/killbill-junction.iml
@@ -12,19 +12,34 @@
     </content>
     <orderEntry type="inheritedJdk" />
     <orderEntry type="sourceFolder" forTests="false" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-catalog:test-jar:tests:0.3.6-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-payment:0.3.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-clock:0.1.7" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-queue:0.1.7" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-jdbi:0.1.7" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-notification:0.3.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-entitlement:test-jar:tests:0.3.6-SNAPSHOT" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-util:test-jar:tests:0.3.6-SNAPSHOT" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing.commons:killbill-clock:test-jar:tests:0.1.7" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing:killbill-api:0.6.0-SNAPSHOT" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-catalog:test-jar:tests:0.5.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-payment:0.4.0-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-notification:0.4.0-SNAPSHOT" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-entitlement:test-jar:tests:0.5.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-util:test-jar:tests:0.5.1-SNAPSHOT" level="project" />
     <orderEntry type="library" scope="PROVIDED" name="Maven: com.google.code.findbugs:jsr305:1.3.9" level="project" />
     <orderEntry type="library" scope="PROVIDED" name="Maven: com.google.guava:guava:14.0.1" level="project" />
     <orderEntry type="library" scope="PROVIDED" name="Maven: com.google.inject:guice:3.0" level="project" />
     <orderEntry type="library" scope="PROVIDED" name="Maven: javax.inject:javax.inject:1" level="project" />
     <orderEntry type="library" scope="PROVIDED" name="Maven: aopalliance:aopalliance:1.0" level="project" />
     <orderEntry type="library" scope="TEST" name="Maven: com.h2database:h2:1.3.158" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing:killbill-api:0.3.3-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing:killbill-api:0.6.0-SNAPSHOT" level="project" />
     <orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-annotations:2.1.0" level="project" />
     <orderEntry type="library" name="Maven: joda-time:joda-time:2.0" level="project" />
     <orderEntry type="module" module-name="killbill-catalog" scope="TEST" production-on-test="" />
-    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-catalog:test-jar:tests:0.3.6-SNAPSHOT" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-catalog:test-jar:tests:0.5.1-SNAPSHOT" level="project" />
     <orderEntry type="module" module-name="killbill-internal-api" />
-    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-payment:0.3.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-payment:0.4.0-SNAPSHOT" level="project" />
     <orderEntry type="library" name="Maven: org.skife.config:config-magic:0.14" level="project" />
     <orderEntry type="library" name="Maven: org.slf4j:slf4j-api:1.7.5" level="project" />
     <orderEntry type="module" module-name="killbill-util" />
@@ -35,13 +50,14 @@
     <orderEntry type="library" name="Maven: com.jolbox:bonecp:0.7.1.RELEASE" level="project" />
     <orderEntry type="library" name="Maven: com.mchange:c3p0:0.9.2" level="project" />
     <orderEntry type="library" name="Maven: com.mchange:mchange-commons-java:0.2.3.3" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-clock:0.1.7" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-queue:0.1.7" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-jdbi:0.1.7" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-clock:0.2.1" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-locker:0.2.1" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-queue:0.2.1" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-jdbi:0.2.1" level="project" />
     <orderEntry type="library" name="Maven: org.jdbi:jdbi:2.39.1" level="project" />
     <orderEntry type="library" name="Maven: com.yammer.metrics:metrics-core:2.1.2" level="project" />
     <orderEntry type="library" name="Maven: org.weakref:jmxutils:1.12" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-notification:0.3.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-notification:0.4.0-SNAPSHOT" level="project" />
     <orderEntry type="library" name="Maven: com.samskivert:jmustache:1.5" level="project" />
     <orderEntry type="library" name="Maven: net.sf.ehcache:ehcache-core:2.6.2" level="project" />
     <orderEntry type="library" name="Maven: org.antlr:stringtemplate:3.2.1" level="project" />
@@ -49,14 +65,21 @@
     <orderEntry type="library" name="Maven: org.apache.commons:commons-email:1.2" level="project" />
     <orderEntry type="library" name="Maven: javax.mail:mail:1.4.1" level="project" />
     <orderEntry type="library" name="Maven: javax.activation:activation:1.1" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.shiro:shiro-core:1.2.2" level="project" />
+    <orderEntry type="library" name="Maven: commons-beanutils:commons-beanutils:1.8.3" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.shiro:shiro-ehcache:1.2.2" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.shiro:shiro-guice:1.2.2" level="project" />
+    <orderEntry type="library" scope="PROVIDED" name="Maven: com.google.inject.extensions:guice-multibindings:3.0" level="project" />
+    <orderEntry type="library" name="Maven: org.slf4j:jcl-over-slf4j:1.7.5" level="project" />
     <orderEntry type="module" module-name="killbill-catalog" scope="TEST" />
     <orderEntry type="module" module-name="killbill-entitlement" scope="TEST" production-on-test="" />
-    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-entitlement:test-jar:tests:0.3.6-SNAPSHOT" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-entitlement:test-jar:tests:0.5.1-SNAPSHOT" level="project" />
     <orderEntry type="module" module-name="killbill-account" scope="TEST" />
     <orderEntry type="module" module-name="killbill-entitlement" scope="TEST" />
     <orderEntry type="module" module-name="killbill-util" scope="TEST" production-on-test="" />
-    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-util:test-jar:tests:0.3.6-SNAPSHOT" level="project" />
-    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing.commons:killbill-clock:test-jar:tests:0.1.7" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-util:test-jar:tests:0.5.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing.commons:killbill-clock:test-jar:tests:0.2.1" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing.commons:killbill-embeddeddb:0.2.1" level="project" />
     <orderEntry type="library" scope="RUNTIME" name="Maven: mysql:mysql-connector-java:5.1.22" level="project" />
     <orderEntry type="library" scope="TEST" name="Maven: mysql:mysql-connector-mxj:5.0.12" level="project" />
     <orderEntry type="library" scope="TEST" name="Maven: mysql:mysql-connector-mxj-db-files:5.0.12" level="project" />

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

diff --git a/junction/pom.xml b/junction/pom.xml
index d97a14c..4d8e3a8 100644
--- a/junction/pom.xml
+++ b/junction/pom.xml
@@ -19,7 +19,7 @@
     <parent>
         <artifactId>killbill</artifactId>
         <groupId>com.ning.billing</groupId>
-        <version>0.3.6-SNAPSHOT</version>
+        <version>0.5.1-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <artifactId>killbill-junction</artifactId>
@@ -101,6 +101,11 @@
         </dependency>
         <dependency>
             <groupId>com.ning.billing.commons</groupId>
+            <artifactId>killbill-embeddeddb</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.ning.billing.commons</groupId>
             <artifactId>killbill-queue</artifactId>
         </dependency>
         <dependency>

NEWS 16(+16 -0)

diff --git a/NEWS b/NEWS
new file mode 100644
index 0000000..b8792f2
--- /dev/null
+++ b/NEWS
@@ -0,0 +1,16 @@
+0.5.0
+    Initial implementation of RBAC
+     - default credentials: admin/password
+    Remove analytics plugin from defaultbundles package
+    Switch to killbill-commons for locker and db testing helper
+    Lower the default number of hash iterations for the apiSecret to 200,000 down from 500,000
+     - you can override it via -Dkillbill.server.multitenant.hash_iterations
+
+0.4.0
+    Search APIs
+    Log errors during lifecycle
+    Fix Catalog endpoints
+
+0.3.6
+    Add all ISO currencies to the catalog
+    jaxrs: return properly formatted JSON in case of exception
diff --git a/osgi/killbill-osgi.iml b/osgi/killbill-osgi.iml
index 1db52ef..29927c0 100644
--- a/osgi/killbill-osgi.iml
+++ b/osgi/killbill-osgi.iml
@@ -11,6 +11,13 @@
     </content>
     <orderEntry type="inheritedJdk" />
     <orderEntry type="sourceFolder" forTests="false" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-payment:0.3.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-clock:0.1.7" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-queue:0.1.7" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-jdbi:0.1.7" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-notification:0.3.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-util:test-jar:tests:0.3.6-SNAPSHOT" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing.commons:killbill-clock:test-jar:tests:0.1.7" level="project" />
     <orderEntry type="library" scope="PROVIDED" name="Maven: com.google.guava:guava:14.0.1" level="project" />
     <orderEntry type="library" scope="PROVIDED" name="Maven: com.google.inject:guice:3.0" level="project" />
     <orderEntry type="library" scope="PROVIDED" name="Maven: javax.inject:javax.inject:1" level="project" />
@@ -20,11 +27,11 @@
     <orderEntry type="library" scope="TEST" name="Maven: org.hamcrest:hamcrest-core:1.1" level="project" />
     <orderEntry type="library" scope="TEST" name="Maven: cglib:cglib-nodep:2.2" level="project" />
     <orderEntry type="library" scope="TEST" name="Maven: org.objenesis:objenesis:1.2" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing:killbill-api:0.3.3-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing:killbill-api:0.6.0-SNAPSHOT" level="project" />
     <orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-annotations:2.1.0" level="project" />
     <orderEntry type="library" name="Maven: joda-time:joda-time:2.0" level="project" />
     <orderEntry type="module" module-name="killbill-internal-api" />
-    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-payment:0.3.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-payment:0.4.0-SNAPSHOT" level="project" />
     <orderEntry type="library" name="Maven: org.skife.config:config-magic:0.14" level="project" />
     <orderEntry type="library" name="Maven: org.slf4j:slf4j-api:1.7.5" level="project" />
     <orderEntry type="module" module-name="killbill-osgi-bundles-lib-killbill" />
@@ -39,14 +46,15 @@
     <orderEntry type="library" name="Maven: com.jolbox:bonecp:0.7.1.RELEASE" level="project" />
     <orderEntry type="library" name="Maven: com.mchange:c3p0:0.9.2" level="project" />
     <orderEntry type="library" name="Maven: com.mchange:mchange-commons-java:0.2.3.3" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-clock:0.1.7" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-queue:0.1.7" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-clock:0.2.1" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-locker:0.2.1" level="project" />
     <orderEntry type="library" scope="TEST" name="Maven: com.h2database:h2:1.3.158" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-jdbi:0.1.7" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-queue:0.2.1" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-jdbi:0.2.1" level="project" />
     <orderEntry type="library" name="Maven: org.jdbi:jdbi:2.39.1" level="project" />
     <orderEntry type="library" name="Maven: com.yammer.metrics:metrics-core:2.1.2" level="project" />
     <orderEntry type="library" name="Maven: org.weakref:jmxutils:1.12" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-notification:0.3.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-notification:0.4.0-SNAPSHOT" level="project" />
     <orderEntry type="library" name="Maven: com.samskivert:jmustache:1.5" level="project" />
     <orderEntry type="library" name="Maven: net.sf.ehcache:ehcache-core:2.6.2" level="project" />
     <orderEntry type="library" name="Maven: org.antlr:stringtemplate:3.2.1" level="project" />
@@ -54,9 +62,15 @@
     <orderEntry type="library" name="Maven: org.apache.commons:commons-email:1.2" level="project" />
     <orderEntry type="library" name="Maven: javax.mail:mail:1.4.1" level="project" />
     <orderEntry type="library" name="Maven: javax.activation:activation:1.1" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.shiro:shiro-core:1.2.2" level="project" />
+    <orderEntry type="library" name="Maven: commons-beanutils:commons-beanutils:1.8.3" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.shiro:shiro-ehcache:1.2.2" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.shiro:shiro-guice:1.2.2" level="project" />
+    <orderEntry type="library" scope="PROVIDED" name="Maven: com.google.inject.extensions:guice-multibindings:3.0" level="project" />
+    <orderEntry type="library" name="Maven: org.slf4j:jcl-over-slf4j:1.7.5" level="project" />
     <orderEntry type="module" module-name="killbill-util" scope="TEST" production-on-test="" />
-    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-util:test-jar:tests:0.3.6-SNAPSHOT" level="project" />
-    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing.commons:killbill-clock:test-jar:tests:0.1.7" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-util:test-jar:tests:0.5.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing.commons:killbill-clock:test-jar:tests:0.2.1" level="project" />
     <orderEntry type="library" scope="PROVIDED" name="Maven: javax.servlet:javax.servlet-api:3.0.1" level="project" />
     <orderEntry type="library" name="Maven: org.apache.felix:org.apache.felix.framework:4.0.3" level="project" />
     <orderEntry type="library" name="Maven: org.apache.felix:org.osgi.core:1.0.1" level="project" />

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

diff --git a/osgi/pom.xml b/osgi/pom.xml
index b3107d6..513b9b9 100644
--- a/osgi/pom.xml
+++ b/osgi/pom.xml
@@ -19,7 +19,7 @@
     <parent>
         <artifactId>killbill</artifactId>
         <groupId>com.ning.billing</groupId>
-        <version>0.3.6-SNAPSHOT</version>
+        <version>0.5.1-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <artifactId>killbill-osgi</artifactId>
diff --git a/osgi-bundles/bundles/jruby/killbill-osgi-bundles-jruby.iml b/osgi-bundles/bundles/jruby/killbill-osgi-bundles-jruby.iml
index 516cb6d..b979d01 100644
--- a/osgi-bundles/bundles/jruby/killbill-osgi-bundles-jruby.iml
+++ b/osgi-bundles/bundles/jruby/killbill-osgi-bundles-jruby.iml
@@ -9,17 +9,23 @@
     </content>
     <orderEntry type="inheritedJdk" />
     <orderEntry type="sourceFolder" forTests="false" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-notification:0.3.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-payment:0.3.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-concurrent:0.1.7" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing:killbill-api:0.6.0-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-notification:0.4.0-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-payment:0.4.0-SNAPSHOT" level="project" />
     <orderEntry type="library" name="Maven: com.google.guava:guava:14.0.1" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing:killbill-api:0.3.3-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing:killbill-api:0.6.0-SNAPSHOT" level="project" />
     <orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-annotations:2.1.0" level="project" />
     <orderEntry type="library" name="Maven: joda-time:joda-time:2.0" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-notification:0.3.1-SNAPSHOT" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-payment:0.3.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-notification:0.4.0-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-payment:0.4.0-SNAPSHOT" level="project" />
     <orderEntry type="module" module-name="killbill-osgi-bundles-lib-killbill" />
     <orderEntry type="library" scope="PROVIDED" name="Maven: com.google.code.findbugs:jsr305:1.3.9" level="project" />
     <orderEntry type="library" name="Maven: org.osgi:org.osgi.compendium:4.3.1" level="project" />
     <orderEntry type="library" name="Maven: org.slf4j:osgi-over-slf4j:1.7.5" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-concurrent:0.1.7" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-concurrent:0.2.1" level="project" />
     <orderEntry type="library" name="Maven: org.slf4j:slf4j-api:1.7.5" level="project" />
     <orderEntry type="library" scope="PROVIDED" name="Maven: javax.servlet:javax.servlet-api:3.0.1" level="project" />
     <orderEntry type="library" name="Maven: org.jruby:jruby-complete:1.7.1" level="project" />
diff --git a/osgi-bundles/bundles/jruby/pom.xml b/osgi-bundles/bundles/jruby/pom.xml
index 188db3e..d304a37 100644
--- a/osgi-bundles/bundles/jruby/pom.xml
+++ b/osgi-bundles/bundles/jruby/pom.xml
@@ -20,7 +20,7 @@
     <parent>
         <groupId>com.ning.billing</groupId>
         <artifactId>killbill-osgi-bundles</artifactId>
-        <version>0.3.6-SNAPSHOT</version>
+        <version>0.5.1-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <artifactId>killbill-osgi-bundles-jruby</artifactId>
diff --git a/osgi-bundles/bundles/jruby/src/main/java/com/ning/billing/osgi/bundles/jruby/JRubyPaymentPlugin.java b/osgi-bundles/bundles/jruby/src/main/java/com/ning/billing/osgi/bundles/jruby/JRubyPaymentPlugin.java
index 4b6a0fa..4868c1f 100644
--- a/osgi-bundles/bundles/jruby/src/main/java/com/ning/billing/osgi/bundles/jruby/JRubyPaymentPlugin.java
+++ b/osgi-bundles/bundles/jruby/src/main/java/com/ning/billing/osgi/bundles/jruby/JRubyPaymentPlugin.java
@@ -168,8 +168,13 @@ public class JRubyPaymentPlugin extends JRubyPlugin implements PaymentPluginApi 
     }
 
     @Override
-    public List<PaymentMethodPlugin> searchPaymentMethods(final String s, final TenantContext tenantContext) throws PaymentPluginApiException {
-        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    public List<PaymentMethodPlugin> searchPaymentMethods(final String searchKey, final TenantContext tenantContext) throws PaymentPluginApiException {
+        return callWithRuntimeAndChecking(new PluginCallback(VALIDATION_PLUGIN_TYPE.PAYMENT) {
+            @Override
+            public List<PaymentMethodPlugin> doCall(final Ruby runtime) throws PaymentPluginApiException {
+                return ((PaymentPluginApi) pluginInstance).searchPaymentMethods(searchKey, tenantContext);
+            }
+        });
     }
 
     @Override
@@ -183,6 +188,4 @@ public class JRubyPaymentPlugin extends JRubyPlugin implements PaymentPluginApi 
             }
         });
     }
-
-
 }
diff --git a/osgi-bundles/bundles/logger/pom.xml b/osgi-bundles/bundles/logger/pom.xml
index 041a2c3..ffad240 100644
--- a/osgi-bundles/bundles/logger/pom.xml
+++ b/osgi-bundles/bundles/logger/pom.xml
@@ -19,7 +19,7 @@
     <parent>
         <artifactId>killbill-osgi-bundles</artifactId>
         <groupId>com.ning.billing</groupId>
-        <version>0.3.6-SNAPSHOT</version>
+        <version>0.5.1-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <artifactId>killbill-osgi-bundles-logger</artifactId>
diff --git a/osgi-bundles/bundles/pom.xml b/osgi-bundles/bundles/pom.xml
index 5003802..c671ce3 100644
--- a/osgi-bundles/bundles/pom.xml
+++ b/osgi-bundles/bundles/pom.xml
@@ -19,7 +19,7 @@
     <parent>
         <artifactId>killbill-osgi-all-bundles</artifactId>
         <groupId>com.ning.billing</groupId>
-        <version>0.3.6-SNAPSHOT</version>
+        <version>0.5.1-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <artifactId>killbill-osgi-bundles</artifactId>
diff --git a/osgi-bundles/bundles/webconsolebranding/pom.xml b/osgi-bundles/bundles/webconsolebranding/pom.xml
index 0d21c3b..01ae167 100644
--- a/osgi-bundles/bundles/webconsolebranding/pom.xml
+++ b/osgi-bundles/bundles/webconsolebranding/pom.xml
@@ -19,7 +19,7 @@
     <parent>
         <artifactId>killbill-osgi-bundles</artifactId>
         <groupId>com.ning.billing</groupId>
-        <version>0.3.6-SNAPSHOT</version>
+        <version>0.5.1-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <artifactId>killbill-osgi-bundles-webconsolebranding</artifactId>
diff --git a/osgi-bundles/defaultbundles/killbill-osgi-bundles-defaultbundles.iml b/osgi-bundles/defaultbundles/killbill-osgi-bundles-defaultbundles.iml
index 0912444..fbcbe1a 100644
--- a/osgi-bundles/defaultbundles/killbill-osgi-bundles-defaultbundles.iml
+++ b/osgi-bundles/defaultbundles/killbill-osgi-bundles-defaultbundles.iml
@@ -9,18 +9,24 @@
     <orderEntry type="inheritedJdk" />
     <orderEntry type="sourceFolder" forTests="false" />
     <orderEntry type="library" name="Maven: com.ning.billing:killbill-osgi-bundles-analytics:0.3.3" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-notification:0.3.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-payment:0.3.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-concurrent:0.1.7" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing:killbill-api:0.6.0-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-notification:0.4.0-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-payment:0.4.0-SNAPSHOT" level="project" />
     <orderEntry type="module" module-name="killbill-osgi-bundles-jruby" />
     <orderEntry type="library" scope="PROVIDED" name="Maven: com.google.guava:guava:14.0.1" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing:killbill-api:0.3.3-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing:killbill-api:0.6.0-SNAPSHOT" level="project" />
     <orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-annotations:2.1.0" level="project" />
     <orderEntry type="library" name="Maven: joda-time:joda-time:2.0" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-notification:0.3.1-SNAPSHOT" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-payment:0.3.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-notification:0.4.0-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-payment:0.4.0-SNAPSHOT" level="project" />
     <orderEntry type="module" module-name="killbill-osgi-bundles-lib-killbill" />
     <orderEntry type="library" scope="PROVIDED" name="Maven: com.google.code.findbugs:jsr305:1.3.9" level="project" />
     <orderEntry type="library" name="Maven: org.osgi:org.osgi.compendium:4.3.1" level="project" />
     <orderEntry type="library" name="Maven: org.slf4j:osgi-over-slf4j:1.7.5" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-concurrent:0.1.7" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-concurrent:0.2.1" level="project" />
     <orderEntry type="library" name="Maven: org.slf4j:slf4j-api:1.7.5" level="project" />
     <orderEntry type="library" name="Maven: org.jruby:jruby-complete:1.7.1" level="project" />
     <orderEntry type="library" name="Maven: org.osgi:org.osgi.core:4.3.1" level="project" />
diff --git a/osgi-bundles/defaultbundles/pom.xml b/osgi-bundles/defaultbundles/pom.xml
index ce105e5..3864299 100644
--- a/osgi-bundles/defaultbundles/pom.xml
+++ b/osgi-bundles/defaultbundles/pom.xml
@@ -19,7 +19,7 @@
     <parent>
         <artifactId>killbill-osgi-all-bundles</artifactId>
         <groupId>com.ning.billing</groupId>
-        <version>0.3.6-SNAPSHOT</version>
+        <version>0.5.1-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <artifactId>killbill-osgi-bundles-defaultbundles</artifactId>
@@ -28,10 +28,6 @@
     <dependencies>
         <dependency>
             <groupId>com.ning.billing</groupId>
-            <artifactId>killbill-osgi-bundles-analytics</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>com.ning.billing</groupId>
             <artifactId>killbill-osgi-bundles-jruby</artifactId>
         </dependency>
         <dependency>
diff --git a/osgi-bundles/libs/killbill/killbill-osgi-bundles-lib-killbill.iml b/osgi-bundles/libs/killbill/killbill-osgi-bundles-lib-killbill.iml
index 37ec4d4..cafae6a 100644
--- a/osgi-bundles/libs/killbill/killbill-osgi-bundles-lib-killbill.iml
+++ b/osgi-bundles/libs/killbill/killbill-osgi-bundles-lib-killbill.iml
@@ -12,11 +12,14 @@
     </content>
     <orderEntry type="inheritedJdk" />
     <orderEntry type="sourceFolder" forTests="false" />
+    <orderEntry type="library" scope="PROVIDED" name="Maven: com.ning.billing.plugin:killbill-plugin-api-notification:0.3.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" scope="PROVIDED" name="Maven: com.ning.billing:killbill-api:0.6.0-SNAPSHOT" level="project" />
+    <orderEntry type="library" scope="PROVIDED" name="Maven: com.ning.billing.plugin:killbill-plugin-api-notification:0.4.0-SNAPSHOT" level="project" />
     <orderEntry type="library" name="Maven: com.google.code.findbugs:jsr305:1.3.9" level="project" />
-    <orderEntry type="library" scope="PROVIDED" name="Maven: com.ning.billing:killbill-api:0.3.3-SNAPSHOT" level="project" />
+    <orderEntry type="library" scope="PROVIDED" name="Maven: com.ning.billing:killbill-api:0.6.0-SNAPSHOT" level="project" />
     <orderEntry type="library" scope="PROVIDED" name="Maven: com.fasterxml.jackson.core:jackson-annotations:2.1.0" level="project" />
     <orderEntry type="library" scope="PROVIDED" name="Maven: joda-time:joda-time:2.0" level="project" />
-    <orderEntry type="library" scope="PROVIDED" name="Maven: com.ning.billing.plugin:killbill-plugin-api-notification:0.3.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" scope="PROVIDED" name="Maven: com.ning.billing.plugin:killbill-plugin-api-notification:0.4.0-SNAPSHOT" level="project" />
     <orderEntry type="library" scope="PROVIDED" name="Maven: javax.servlet:javax.servlet-api:3.0.1" level="project" />
     <orderEntry type="library" scope="TEST" name="Maven: org.mockito:mockito-all:1.9.0" level="project" />
     <orderEntry type="library" name="Maven: org.osgi:org.osgi.compendium:4.3.1" level="project" />
diff --git a/osgi-bundles/libs/killbill/pom.xml b/osgi-bundles/libs/killbill/pom.xml
index 2c4bdd3..fc619f1 100644
--- a/osgi-bundles/libs/killbill/pom.xml
+++ b/osgi-bundles/libs/killbill/pom.xml
@@ -19,7 +19,7 @@
     <parent>
         <artifactId>killbill-osgi-lib-bundles</artifactId>
         <groupId>com.ning.billing</groupId>
-        <version>0.3.6-SNAPSHOT</version>
+        <version>0.5.1-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <artifactId>killbill-osgi-bundles-lib-killbill</artifactId>
diff --git a/osgi-bundles/libs/pom.xml b/osgi-bundles/libs/pom.xml
index a28aa3c..5eee1fc 100644
--- a/osgi-bundles/libs/pom.xml
+++ b/osgi-bundles/libs/pom.xml
@@ -19,7 +19,7 @@
     <parent>
         <artifactId>killbill-osgi-all-bundles</artifactId>
         <groupId>com.ning.billing</groupId>
-        <version>0.3.6-SNAPSHOT</version>
+        <version>0.5.1-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <artifactId>killbill-osgi-lib-bundles</artifactId>
diff --git a/osgi-bundles/libs/slf4j-osgi/pom.xml b/osgi-bundles/libs/slf4j-osgi/pom.xml
index 4592356..416d38c 100644
--- a/osgi-bundles/libs/slf4j-osgi/pom.xml
+++ b/osgi-bundles/libs/slf4j-osgi/pom.xml
@@ -19,7 +19,7 @@
     <parent>
         <artifactId>killbill-osgi-lib-bundles</artifactId>
         <groupId>com.ning.billing</groupId>
-        <version>0.3.6-SNAPSHOT</version>
+        <version>0.5.1-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <artifactId>killbill-osgi-bundles-lib-slf4j-osgi</artifactId>
diff --git a/osgi-bundles/pom.xml b/osgi-bundles/pom.xml
index 6c32cbe..3fd20ee 100644
--- a/osgi-bundles/pom.xml
+++ b/osgi-bundles/pom.xml
@@ -19,7 +19,7 @@
     <parent>
         <artifactId>killbill</artifactId>
         <groupId>com.ning.billing</groupId>
-        <version>0.3.6-SNAPSHOT</version>
+        <version>0.5.1-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <artifactId>killbill-osgi-all-bundles</artifactId>
diff --git a/osgi-bundles/tests/beatrix/killbill-osgi-bundles-test-beatrix.iml b/osgi-bundles/tests/beatrix/killbill-osgi-bundles-test-beatrix.iml
index 1e18463..fbc7ff4 100644
--- a/osgi-bundles/tests/beatrix/killbill-osgi-bundles-test-beatrix.iml
+++ b/osgi-bundles/tests/beatrix/killbill-osgi-bundles-test-beatrix.iml
@@ -12,15 +12,17 @@
     </content>
     <orderEntry type="inheritedJdk" />
     <orderEntry type="sourceFolder" forTests="false" />
-    <orderEntry type="library" name="Maven: com.ning.billing:killbill-api:0.3.3-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-notification:0.3.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-payment:0.3.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing:killbill-api:0.6.0-SNAPSHOT" level="project" />
     <orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-annotations:2.1.0" level="project" />
     <orderEntry type="library" name="Maven: joda-time:joda-time:2.0" level="project" />
     <orderEntry type="module" module-name="killbill-osgi-bundles-lib-killbill" />
     <orderEntry type="library" scope="PROVIDED" name="Maven: com.google.code.findbugs:jsr305:1.3.9" level="project" />
     <orderEntry type="library" name="Maven: org.osgi:org.osgi.compendium:4.3.1" level="project" />
     <orderEntry type="library" name="Maven: org.slf4j:osgi-over-slf4j:1.7.5" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-notification:0.3.1-SNAPSHOT" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-payment:0.3.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-notification:0.4.0-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-payment:0.4.0-SNAPSHOT" level="project" />
     <orderEntry type="library" name="Maven: org.jdbi:jdbi:2.39.1" level="project" />
     <orderEntry type="library" scope="TEST" name="Maven: org.mockito:mockito-all:1.9.0" level="project" />
     <orderEntry type="library" name="Maven: org.osgi:org.osgi.core:4.3.1" level="project" />
diff --git a/osgi-bundles/tests/beatrix/pom.xml b/osgi-bundles/tests/beatrix/pom.xml
index a34398b..886e5e2 100644
--- a/osgi-bundles/tests/beatrix/pom.xml
+++ b/osgi-bundles/tests/beatrix/pom.xml
@@ -19,7 +19,7 @@
     <parent>
         <artifactId>killbill-osgi-test-bundles</artifactId>
         <groupId>com.ning.billing</groupId>
-        <version>0.3.6-SNAPSHOT</version>
+        <version>0.5.1-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <artifactId>killbill-osgi-bundles-test-beatrix</artifactId>
diff --git a/osgi-bundles/tests/beatrix/src/test/java/com/ning/billing/osgi/bundles/test/TestPaymentPluginApi.java b/osgi-bundles/tests/beatrix/src/test/java/com/ning/billing/osgi/bundles/test/TestPaymentPluginApi.java
index 365b7c4..600f5af 100644
--- a/osgi-bundles/tests/beatrix/src/test/java/com/ning/billing/osgi/bundles/test/TestPaymentPluginApi.java
+++ b/osgi-bundles/tests/beatrix/src/test/java/com/ning/billing/osgi/bundles/test/TestPaymentPluginApi.java
@@ -53,22 +53,27 @@ public class TestPaymentPluginApi implements PaymentPluginApi {
             public BigDecimal getAmount() {
                 return amount;
             }
+
             @Override
             public DateTime getCreatedDate() {
                 return new DateTime();
             }
+
             @Override
             public DateTime getEffectiveDate() {
                 return new DateTime();
             }
+
             @Override
             public PaymentPluginStatus getStatus() {
                 return PaymentPluginStatus.PROCESSED;
             }
+
             @Override
             public String getGatewayError() {
                 return null;
             }
+
             @Override
             public String getGatewayErrorCode() {
                 return null;
@@ -120,17 +125,15 @@ public class TestPaymentPluginApi implements PaymentPluginApi {
 
     @Override
     public List<PaymentMethodInfoPlugin> getPaymentMethods(final UUID kbAccountId, final boolean refreshFromGateway, final CallContext context) throws PaymentPluginApiException {
-        return null;
+        return Collections.emptyList();
     }
 
     @Override
-    public List<PaymentMethodPlugin> searchPaymentMethods(final String s, final TenantContext tenantContext) throws PaymentPluginApiException {
-        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    public List<PaymentMethodPlugin> searchPaymentMethods(final String searchKey, final TenantContext tenantContext) throws PaymentPluginApiException {
+        return Collections.emptyList();
     }
 
     @Override
     public void resetPaymentMethods(final UUID kbAccountId, final List<PaymentMethodInfoPlugin> paymentMethods) throws PaymentPluginApiException {
     }
-
-
 }
diff --git a/osgi-bundles/tests/payment/killbill-osgi-bundles-test-payment.iml b/osgi-bundles/tests/payment/killbill-osgi-bundles-test-payment.iml
index e636e87..74a9686 100644
--- a/osgi-bundles/tests/payment/killbill-osgi-bundles-test-payment.iml
+++ b/osgi-bundles/tests/payment/killbill-osgi-bundles-test-payment.iml
@@ -11,7 +11,17 @@
     </content>
     <orderEntry type="inheritedJdk" />
     <orderEntry type="sourceFolder" forTests="false" />
-    <orderEntry type="library" name="Maven: com.ning.billing:killbill-api:0.3.3-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing:killbill-util:test-jar:tests:0.3.6-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-payment:0.3.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-clock:0.1.7" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-queue:0.1.7" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-jdbi:0.1.7" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-notification:0.3.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing:killbill-api:0.6.0-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing:killbill-util:test-jar:tests:0.5.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-payment:0.4.0-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-notification:0.4.0-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing:killbill-api:0.6.0-SNAPSHOT" level="project" />
     <orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-annotations:2.1.0" level="project" />
     <orderEntry type="library" name="Maven: joda-time:joda-time:2.0" level="project" />
     <orderEntry type="module" module-name="killbill-osgi-bundles-lib-killbill" />
@@ -19,7 +29,7 @@
     <orderEntry type="library" name="Maven: org.osgi:org.osgi.compendium:4.3.1" level="project" />
     <orderEntry type="library" name="Maven: org.slf4j:osgi-over-slf4j:1.7.5" level="project" />
     <orderEntry type="module" module-name="killbill-util" production-on-test="" />
-    <orderEntry type="library" name="Maven: com.ning.billing:killbill-util:test-jar:tests:0.3.6-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing:killbill-util:test-jar:tests:0.5.1-SNAPSHOT" level="project" />
     <orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-databind:2.1.0" level="project" />
     <orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-core:2.1.0" level="project" />
     <orderEntry type="library" name="Maven: com.fasterxml.jackson.dataformat:jackson-dataformat-csv:2.1.0" level="project" />
@@ -29,16 +39,17 @@
     <orderEntry type="library" name="Maven: com.mchange:c3p0:0.9.2" level="project" />
     <orderEntry type="library" name="Maven: com.mchange:mchange-commons-java:0.2.3.3" level="project" />
     <orderEntry type="module" module-name="killbill-internal-api" />
-    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-payment:0.3.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-payment:0.4.0-SNAPSHOT" level="project" />
     <orderEntry type="library" name="Maven: org.skife.config:config-magic:0.14" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-clock:0.1.7" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-queue:0.1.7" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-clock:0.2.1" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-locker:0.2.1" level="project" />
     <orderEntry type="library" scope="TEST" name="Maven: com.h2database:h2:1.3.158" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-jdbi:0.1.7" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-queue:0.2.1" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-jdbi:0.2.1" level="project" />
     <orderEntry type="library" name="Maven: org.jdbi:jdbi:2.39.1" level="project" />
     <orderEntry type="library" name="Maven: com.yammer.metrics:metrics-core:2.1.2" level="project" />
     <orderEntry type="library" name="Maven: org.weakref:jmxutils:1.12" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-notification:0.3.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-notification:0.4.0-SNAPSHOT" level="project" />
     <orderEntry type="library" name="Maven: com.samskivert:jmustache:1.5" level="project" />
     <orderEntry type="library" name="Maven: net.sf.ehcache:ehcache-core:2.6.2" level="project" />
     <orderEntry type="library" name="Maven: org.antlr:stringtemplate:3.2.1" level="project" />
@@ -46,6 +57,16 @@
     <orderEntry type="library" name="Maven: org.apache.commons:commons-email:1.2" level="project" />
     <orderEntry type="library" name="Maven: javax.mail:mail:1.4.1" level="project" />
     <orderEntry type="library" name="Maven: javax.activation:activation:1.1" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.shiro:shiro-core:1.2.2" level="project" />
+    <orderEntry type="library" name="Maven: commons-beanutils:commons-beanutils:1.8.3" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.shiro:shiro-ehcache:1.2.2" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.shiro:shiro-guice:1.2.2" level="project" />
+    <orderEntry type="library" scope="PROVIDED" name="Maven: com.google.guava:guava:14.0.1" level="project" />
+    <orderEntry type="library" scope="PROVIDED" name="Maven: com.google.inject:guice:3.0" level="project" />
+    <orderEntry type="library" scope="PROVIDED" name="Maven: javax.inject:javax.inject:1" level="project" />
+    <orderEntry type="library" scope="PROVIDED" name="Maven: aopalliance:aopalliance:1.0" level="project" />
+    <orderEntry type="library" scope="PROVIDED" name="Maven: com.google.inject.extensions:guice-multibindings:3.0" level="project" />
+    <orderEntry type="library" name="Maven: org.slf4j:jcl-over-slf4j:1.7.5" level="project" />
     <orderEntry type="library" scope="TEST" name="Maven: org.mockito:mockito-all:1.9.0" level="project" />
     <orderEntry type="library" name="Maven: org.osgi:org.osgi.core:4.3.1" level="project" />
     <orderEntry type="library" scope="TEST" name="Maven: org.testng:testng:6.3.1" level="project" />
diff --git a/osgi-bundles/tests/payment/pom.xml b/osgi-bundles/tests/payment/pom.xml
index 21ec519..41d43cd 100644
--- a/osgi-bundles/tests/payment/pom.xml
+++ b/osgi-bundles/tests/payment/pom.xml
@@ -19,7 +19,7 @@
     <parent>
         <artifactId>killbill-osgi-test-bundles</artifactId>
         <groupId>com.ning.billing</groupId>
-        <version>0.3.6-SNAPSHOT</version>
+        <version>0.5.1-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <artifactId>killbill-osgi-bundles-test-payment</artifactId>
diff --git a/osgi-bundles/tests/payment/src/test/java/com/ning/billing/osgi/bundles/test/TestPaymentPluginApi.java b/osgi-bundles/tests/payment/src/test/java/com/ning/billing/osgi/bundles/test/TestPaymentPluginApi.java
index 9c52b38..804e548 100644
--- a/osgi-bundles/tests/payment/src/test/java/com/ning/billing/osgi/bundles/test/TestPaymentPluginApi.java
+++ b/osgi-bundles/tests/payment/src/test/java/com/ning/billing/osgi/bundles/test/TestPaymentPluginApi.java
@@ -190,12 +190,12 @@ public class TestPaymentPluginApi implements PaymentPluginApiWithTestControl {
 
     @Override
     public List<PaymentMethodInfoPlugin> getPaymentMethods(final UUID kbAccountId, final boolean refreshFromGateway, final CallContext context) throws PaymentPluginApiException {
-        return null;
+        return Collections.emptyList();
     }
 
     @Override
     public List<PaymentMethodPlugin> searchPaymentMethods(final String s, final TenantContext tenantContext) throws PaymentPluginApiException {
-        return null;  //To change body of implemented methods use File | Settings | File Templates.
+        return Collections.emptyList();
     }
 
     @Override
diff --git a/osgi-bundles/tests/pom.xml b/osgi-bundles/tests/pom.xml
index f605491..0a5fa9b 100644
--- a/osgi-bundles/tests/pom.xml
+++ b/osgi-bundles/tests/pom.xml
@@ -19,7 +19,7 @@
     <parent>
         <artifactId>killbill-osgi-all-bundles</artifactId>
         <groupId>com.ning.billing</groupId>
-        <version>0.3.6-SNAPSHOT</version>
+        <version>0.5.1-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <artifactId>killbill-osgi-test-bundles</artifactId>
diff --git a/overdue/killbill-overdue.iml b/overdue/killbill-overdue.iml
index 9388421..af3075d 100644
--- a/overdue/killbill-overdue.iml
+++ b/overdue/killbill-overdue.iml
@@ -11,6 +11,20 @@
     </content>
     <orderEntry type="inheritedJdk" />
     <orderEntry type="sourceFolder" forTests="false" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-catalog:test-jar:tests:0.3.6-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-payment:0.3.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-clock:0.1.7" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-queue:0.1.7" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-jdbi:0.1.7" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-notification:0.3.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-util:test-jar:tests:0.3.6-SNAPSHOT" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing.commons:killbill-clock:test-jar:tests:0.1.7" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing.commons:killbill-queue:test-jar:tests:0.1.7" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing:killbill-api:0.6.0-SNAPSHOT" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-catalog:test-jar:tests:0.5.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-payment:0.4.0-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-notification:0.4.0-SNAPSHOT" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-util:test-jar:tests:0.5.1-SNAPSHOT" level="project" />
     <orderEntry type="library" scope="PROVIDED" name="Maven: com.google.code.findbugs:jsr305:1.3.9" level="project" />
     <orderEntry type="library" scope="PROVIDED" name="Maven: com.google.guava:guava:14.0.1" level="project" />
     <orderEntry type="library" scope="PROVIDED" name="Maven: com.google.inject:guice:3.0" level="project" />
@@ -22,13 +36,13 @@
     <orderEntry type="library" scope="TEST" name="Maven: org.hamcrest:hamcrest-core:1.1" level="project" />
     <orderEntry type="library" scope="TEST" name="Maven: cglib:cglib-nodep:2.2" level="project" />
     <orderEntry type="library" scope="TEST" name="Maven: org.objenesis:objenesis:1.2" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing:killbill-api:0.3.3-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing:killbill-api:0.6.0-SNAPSHOT" level="project" />
     <orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-annotations:2.1.0" level="project" />
     <orderEntry type="library" name="Maven: joda-time:joda-time:2.0" level="project" />
     <orderEntry type="module" module-name="killbill-catalog" scope="TEST" production-on-test="" />
-    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-catalog:test-jar:tests:0.3.6-SNAPSHOT" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-catalog:test-jar:tests:0.5.1-SNAPSHOT" level="project" />
     <orderEntry type="module" module-name="killbill-internal-api" />
-    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-payment:0.3.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-payment:0.4.0-SNAPSHOT" level="project" />
     <orderEntry type="library" name="Maven: org.skife.config:config-magic:0.14" level="project" />
     <orderEntry type="library" name="Maven: org.slf4j:slf4j-api:1.7.5" level="project" />
     <orderEntry type="module" module-name="killbill-util" />
@@ -39,13 +53,14 @@
     <orderEntry type="library" name="Maven: com.jolbox:bonecp:0.7.1.RELEASE" level="project" />
     <orderEntry type="library" name="Maven: com.mchange:c3p0:0.9.2" level="project" />
     <orderEntry type="library" name="Maven: com.mchange:mchange-commons-java:0.2.3.3" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-clock:0.1.7" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-queue:0.1.7" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-jdbi:0.1.7" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-clock:0.2.1" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-locker:0.2.1" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-queue:0.2.1" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-jdbi:0.2.1" level="project" />
     <orderEntry type="library" name="Maven: org.jdbi:jdbi:2.39.1" level="project" />
     <orderEntry type="library" name="Maven: com.yammer.metrics:metrics-core:2.1.2" level="project" />
     <orderEntry type="library" name="Maven: org.weakref:jmxutils:1.12" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-notification:0.3.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-notification:0.4.0-SNAPSHOT" level="project" />
     <orderEntry type="library" name="Maven: com.samskivert:jmustache:1.5" level="project" />
     <orderEntry type="library" name="Maven: net.sf.ehcache:ehcache-core:2.6.2" level="project" />
     <orderEntry type="library" name="Maven: org.antlr:stringtemplate:3.2.1" level="project" />
@@ -53,11 +68,18 @@
     <orderEntry type="library" name="Maven: org.apache.commons:commons-email:1.2" level="project" />
     <orderEntry type="library" name="Maven: javax.mail:mail:1.4.1" level="project" />
     <orderEntry type="library" name="Maven: javax.activation:activation:1.1" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.shiro:shiro-core:1.2.2" level="project" />
+    <orderEntry type="library" name="Maven: commons-beanutils:commons-beanutils:1.8.3" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.shiro:shiro-ehcache:1.2.2" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.shiro:shiro-guice:1.2.2" level="project" />
+    <orderEntry type="library" scope="PROVIDED" name="Maven: com.google.inject.extensions:guice-multibindings:3.0" level="project" />
+    <orderEntry type="library" name="Maven: org.slf4j:jcl-over-slf4j:1.7.5" level="project" />
     <orderEntry type="module" module-name="killbill-catalog" scope="TEST" />
     <orderEntry type="module" module-name="killbill-util" scope="TEST" production-on-test="" />
-    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-util:test-jar:tests:0.3.6-SNAPSHOT" level="project" />
-    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing.commons:killbill-clock:test-jar:tests:0.1.7" level="project" />
-    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing.commons:killbill-queue:test-jar:tests:0.1.7" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-util:test-jar:tests:0.5.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing.commons:killbill-clock:test-jar:tests:0.2.1" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing.commons:killbill-embeddeddb:0.2.1" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing.commons:killbill-queue:test-jar:tests:0.2.1" level="project" />
     <orderEntry type="library" scope="RUNTIME" name="Maven: mysql:mysql-connector-java:5.1.22" level="project" />
     <orderEntry type="library" scope="TEST" name="Maven: mysql:mysql-connector-mxj:5.0.12" level="project" />
     <orderEntry type="library" scope="TEST" name="Maven: mysql:mysql-connector-mxj-db-files:5.0.12" level="project" />

overdue/pom.xml 8(+6 -2)

diff --git a/overdue/pom.xml b/overdue/pom.xml
index 3b501aa..b6b6095 100644
--- a/overdue/pom.xml
+++ b/overdue/pom.xml
@@ -19,7 +19,7 @@
     <parent>
         <artifactId>killbill</artifactId>
         <groupId>com.ning.billing</groupId>
-        <version>0.3.6-SNAPSHOT</version>
+        <version>0.5.1-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <artifactId>killbill-overdue</artifactId>
@@ -91,9 +91,13 @@
         </dependency>
         <dependency>
             <groupId>com.ning.billing.commons</groupId>
+            <artifactId>killbill-embeddeddb</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.ning.billing.commons</groupId>
             <artifactId>killbill-queue</artifactId>
         </dependency>
-
         <dependency>
             <groupId>com.ning.billing.commons</groupId>
             <artifactId>killbill-queue</artifactId>
diff --git a/overdue/src/main/java/com/ning/billing/overdue/applicator/OverdueStateApplicator.java b/overdue/src/main/java/com/ning/billing/overdue/applicator/OverdueStateApplicator.java
index 21a489f..394a851 100644
--- a/overdue/src/main/java/com/ning/billing/overdue/applicator/OverdueStateApplicator.java
+++ b/overdue/src/main/java/com/ning/billing/overdue/applicator/OverdueStateApplicator.java
@@ -41,7 +41,7 @@ import com.ning.billing.entitlement.api.EntitlementApi;
 import com.ning.billing.entitlement.api.EntitlementApiException;
 import com.ning.billing.ovedue.notification.OverdueCheckPoster;
 import com.ning.billing.overdue.OverdueApiException;
-import com.ning.billing.overdue.OverdueCancellationPolicicy;
+import com.ning.billing.overdue.OverdueCancellationPolicy;
 import com.ning.billing.overdue.OverdueService;
 import com.ning.billing.overdue.OverdueState;
 import com.ning.billing.overdue.config.api.BillingState;
@@ -202,7 +202,7 @@ public class OverdueStateApplicator {
     }
 
     private void cancelSubscriptionsIfRequired(final Account account, final OverdueState nextOverdueState, final InternalCallContext context) throws OverdueException {
-        if (nextOverdueState.getSubscriptionCancellationPolicy() == OverdueCancellationPolicicy.NONE) {
+        if (nextOverdueState.getSubscriptionCancellationPolicy() == OverdueCancellationPolicy.NONE) {
             return;
         }
         try {
@@ -229,7 +229,8 @@ public class OverdueStateApplicator {
 
     @SuppressWarnings("unchecked")
     private void computeEntitlementsToCancel(final Account blockable, final List<Entitlement> result, final InternalTenantContext context) throws EntitlementApiException {
-        result.addAll(entitlementApi.getAllEntitlementsForAccountId(blockable.getId(), context.toTenantContext()));
+        // STEPH_ENT fix internal API.
+        result.addAll(entitlementApi.getAllEntitlementsForAccountId(blockable.getId(), context.toTenantContext(null)));
     }
 
     private void sendEmailIfRequired(final BillingState billingState, final Account account,
diff --git a/overdue/src/main/java/com/ning/billing/overdue/config/DefaultOverdueState.java b/overdue/src/main/java/com/ning/billing/overdue/config/DefaultOverdueState.java
index fb6b78b..b69b6f4 100644
--- a/overdue/src/main/java/com/ning/billing/overdue/config/DefaultOverdueState.java
+++ b/overdue/src/main/java/com/ning/billing/overdue/config/DefaultOverdueState.java
@@ -28,7 +28,7 @@ import com.ning.billing.ErrorCode;
 import com.ning.billing.catalog.api.TimeUnit;
 import com.ning.billing.overdue.EmailNotification;
 import com.ning.billing.overdue.OverdueApiException;
-import com.ning.billing.overdue.OverdueCancellationPolicicy;
+import com.ning.billing.overdue.OverdueCancellationPolicy;
 import com.ning.billing.overdue.OverdueState;
 import com.ning.billing.util.config.catalog.ValidatingConfig;
 import com.ning.billing.util.config.catalog.ValidationError;
@@ -56,7 +56,7 @@ public class DefaultOverdueState extends ValidatingConfig<OverdueConfig> impleme
     private Boolean disableEntitlement = false;
 
     @XmlElement(required = false, name = "subscriptionCancellationPolicy")
-    private OverdueCancellationPolicicy subscriptionCancellationPolicy = OverdueCancellationPolicicy.NONE;
+    private OverdueCancellationPolicy subscriptionCancellationPolicy = OverdueCancellationPolicy.NONE;
 
     @XmlElement(required = false, name = "isClearState")
     private Boolean isClearState = false;
@@ -95,7 +95,7 @@ public class DefaultOverdueState extends ValidatingConfig<OverdueConfig> impleme
     }
 
     @Override
-    public OverdueCancellationPolicicy getSubscriptionCancellationPolicy() {
+    public OverdueCancellationPolicy getSubscriptionCancellationPolicy() {
         return subscriptionCancellationPolicy;
     }
 
@@ -132,7 +132,7 @@ public class DefaultOverdueState extends ValidatingConfig<OverdueConfig> impleme
         return this;
     }
 
-    public DefaultOverdueState setSubscriptionCancellationPolicy(final OverdueCancellationPolicicy policy) {
+    public DefaultOverdueState setSubscriptionCancellationPolicy(final OverdueCancellationPolicy policy) {
         this.subscriptionCancellationPolicy = policy;
         return this;
     }
diff --git a/overdue/src/main/java/com/ning/billing/overdue/wrapper/OverdueWrapperFactory.java b/overdue/src/main/java/com/ning/billing/overdue/wrapper/OverdueWrapperFactory.java
index fcc4ea7..7b9fe94 100644
--- a/overdue/src/main/java/com/ning/billing/overdue/wrapper/OverdueWrapperFactory.java
+++ b/overdue/src/main/java/com/ning/billing/overdue/wrapper/OverdueWrapperFactory.java
@@ -71,7 +71,8 @@ public class OverdueWrapperFactory {
     public OverdueWrapper createOverdueWrapperFor(final UUID id, final InternalTenantContext context) throws OverdueException {
 
         try {
-            Account account = accountUserApi.getAccountById(id, context.toTenantContext());
+            // STEPH_ENT
+            Account account = accountUserApi.getAccountById(id, context.toTenantContext(null));
             return new OverdueWrapper(account, api, getOverdueStateSetBundle(),
                                       clock, billingStateCalculator, overdueStateApplicator);
 
diff --git a/overdue/src/test/java/com/ning/billing/ovedue/notification/TestDefaultOverdueCheckPoster.java b/overdue/src/test/java/com/ning/billing/ovedue/notification/TestDefaultOverdueCheckPoster.java
index 3bf770f..e44cd73 100644
--- a/overdue/src/test/java/com/ning/billing/ovedue/notification/TestDefaultOverdueCheckPoster.java
+++ b/overdue/src/test/java/com/ning/billing/ovedue/notification/TestDefaultOverdueCheckPoster.java
@@ -52,7 +52,7 @@ public class TestDefaultOverdueCheckPoster extends OverdueTestSuiteWithEmbeddedD
     @BeforeMethod(groups = "slow")
     public void beforeMethod() throws Exception {
         super.beforeMethod();
-        entitySqlDaoTransactionalJdbiWrapper = new EntitySqlDaoTransactionalJdbiWrapper(getDBI(), clock, cacheControllerDispatcher, nonEntityDao);
+        entitySqlDaoTransactionalJdbiWrapper = new EntitySqlDaoTransactionalJdbiWrapper(dbi, clock, cacheControllerDispatcher, nonEntityDao);
 
         overdueQueue = notificationQueueService.getNotificationQueue(DefaultOverdueService.OVERDUE_SERVICE_NAME,
                                                                      DefaultOverdueCheckNotifier.OVERDUE_CHECK_NOTIFIER_QUEUE);
diff --git a/payment/killbill-payment.iml b/payment/killbill-payment.iml
index d8fcd04..97fa80c 100644
--- a/payment/killbill-payment.iml
+++ b/payment/killbill-payment.iml
@@ -12,6 +12,17 @@
     </content>
     <orderEntry type="inheritedJdk" />
     <orderEntry type="sourceFolder" forTests="false" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-account:test-jar:tests:0.3.6-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-payment:0.3.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-clock:0.1.7" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-queue:0.1.7" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-jdbi:0.1.7" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-notification:0.3.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-invoice:test-jar:tests:0.3.6-SNAPSHOT" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-junction:test-jar:tests:0.3.6-SNAPSHOT" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-util:test-jar:tests:0.3.6-SNAPSHOT" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing.commons:killbill-clock:test-jar:tests:0.1.7" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing.commons:killbill-queue:test-jar:tests:0.1.7" level="project" />
     <orderEntry type="library" scope="PROVIDED" name="Maven: com.google.code.findbugs:jsr305:1.3.9" level="project" />
     <orderEntry type="library" scope="PROVIDED" name="Maven: com.google.guava:guava:14.0.1" level="project" />
     <orderEntry type="library" scope="PROVIDED" name="Maven: com.google.inject:guice:3.0" level="project" />
@@ -25,14 +36,14 @@
     <orderEntry type="library" scope="TEST" name="Maven: cglib:cglib-nodep:2.2" level="project" />
     <orderEntry type="library" scope="TEST" name="Maven: org.objenesis:objenesis:1.2" level="project" />
     <orderEntry type="module" module-name="killbill-account" scope="TEST" production-on-test="" />
-    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-account:test-jar:tests:0.3.6-SNAPSHOT" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-account:test-jar:tests:0.5.1-SNAPSHOT" level="project" />
     <orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-annotations:2.1.0" level="project" />
     <orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-databind:2.1.0" level="project" />
     <orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-core:2.1.0" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing:killbill-api:0.3.3-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing:killbill-api:0.6.0-SNAPSHOT" level="project" />
     <orderEntry type="library" name="Maven: joda-time:joda-time:2.0" level="project" />
     <orderEntry type="module" module-name="killbill-internal-api" />
-    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-payment:0.3.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-payment:0.4.0-SNAPSHOT" level="project" />
     <orderEntry type="library" name="Maven: org.skife.config:config-magic:0.14" level="project" />
     <orderEntry type="library" name="Maven: org.slf4j:slf4j-api:1.7.5" level="project" />
     <orderEntry type="module" module-name="killbill-util" />
@@ -41,13 +52,14 @@
     <orderEntry type="library" name="Maven: com.jolbox:bonecp:0.7.1.RELEASE" level="project" />
     <orderEntry type="library" name="Maven: com.mchange:c3p0:0.9.2" level="project" />
     <orderEntry type="library" name="Maven: com.mchange:mchange-commons-java:0.2.3.3" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-clock:0.1.7" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-queue:0.1.7" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-jdbi:0.1.7" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-clock:0.2.1" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-locker:0.2.1" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-queue:0.2.1" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-jdbi:0.2.1" level="project" />
     <orderEntry type="library" name="Maven: org.jdbi:jdbi:2.39.1" level="project" />
     <orderEntry type="library" name="Maven: com.yammer.metrics:metrics-core:2.1.2" level="project" />
     <orderEntry type="library" name="Maven: org.weakref:jmxutils:1.12" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-notification:0.3.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-notification:0.4.0-SNAPSHOT" level="project" />
     <orderEntry type="library" name="Maven: com.samskivert:jmustache:1.5" level="project" />
     <orderEntry type="library" name="Maven: net.sf.ehcache:ehcache-core:2.6.2" level="project" />
     <orderEntry type="library" name="Maven: org.antlr:stringtemplate:3.2.1" level="project" />
@@ -55,15 +67,21 @@
     <orderEntry type="library" name="Maven: org.apache.commons:commons-email:1.2" level="project" />
     <orderEntry type="library" name="Maven: javax.mail:mail:1.4.1" level="project" />
     <orderEntry type="library" name="Maven: javax.activation:activation:1.1" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.shiro:shiro-core:1.2.2" level="project" />
+    <orderEntry type="library" name="Maven: commons-beanutils:commons-beanutils:1.8.3" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.shiro:shiro-ehcache:1.2.2" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.shiro:shiro-guice:1.2.2" level="project" />
+    <orderEntry type="library" name="Maven: org.slf4j:jcl-over-slf4j:1.7.5" level="project" />
     <orderEntry type="module" module-name="killbill-invoice" scope="TEST" production-on-test="" />
-    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-invoice:test-jar:tests:0.3.6-SNAPSHOT" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-invoice:test-jar:tests:0.5.1-SNAPSHOT" level="project" />
     <orderEntry type="module" module-name="killbill-junction" scope="TEST" production-on-test="" />
-    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-junction:test-jar:tests:0.3.6-SNAPSHOT" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-junction:test-jar:tests:0.5.1-SNAPSHOT" level="project" />
     <orderEntry type="library" scope="RUNTIME" name="Maven: mysql:mysql-connector-java:5.1.22" level="project" />
     <orderEntry type="module" module-name="killbill-util" scope="TEST" production-on-test="" />
-    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-util:test-jar:tests:0.3.6-SNAPSHOT" level="project" />
-    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing.commons:killbill-clock:test-jar:tests:0.1.7" level="project" />
-    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing.commons:killbill-queue:test-jar:tests:0.1.7" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-util:test-jar:tests:0.5.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing.commons:killbill-clock:test-jar:tests:0.2.1" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing.commons:killbill-embeddeddb:0.2.1" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing.commons:killbill-queue:test-jar:tests:0.2.1" level="project" />
     <orderEntry type="library" scope="TEST" name="Maven: mysql:mysql-connector-mxj:5.0.12" level="project" />
     <orderEntry type="library" scope="TEST" name="Maven: mysql:mysql-connector-mxj-db-files:5.0.12" level="project" />
     <orderEntry type="library" scope="TEST" name="Maven: org.mockito:mockito-all:1.9.0" level="project" />

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

diff --git a/payment/pom.xml b/payment/pom.xml
index 5aa5233..3309a7b 100644
--- a/payment/pom.xml
+++ b/payment/pom.xml
@@ -19,7 +19,7 @@
     <parent>
         <artifactId>killbill</artifactId>
         <groupId>com.ning.billing</groupId>
-        <version>0.3.6-SNAPSHOT</version>
+        <version>0.5.1-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <artifactId>killbill-payment</artifactId>
@@ -104,6 +104,11 @@
         </dependency>
         <dependency>
             <groupId>com.ning.billing.commons</groupId>
+            <artifactId>killbill-embeddeddb</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.ning.billing.commons</groupId>
             <artifactId>killbill-queue</artifactId>
         </dependency>
         <dependency>
diff --git a/payment/src/main/java/com/ning/billing/payment/api/DefaultPaymentApi.java b/payment/src/main/java/com/ning/billing/payment/api/DefaultPaymentApi.java
index 394c848..943f9d6 100644
--- a/payment/src/main/java/com/ning/billing/payment/api/DefaultPaymentApi.java
+++ b/payment/src/main/java/com/ning/billing/payment/api/DefaultPaymentApi.java
@@ -173,6 +173,16 @@ public class DefaultPaymentApi implements PaymentApi {
     }
 
     @Override
+    public List<PaymentMethod> searchPaymentMethods(final String searchKey, final TenantContext context) {
+        return methodProcessor.searchPaymentMethods(searchKey, internalCallContextFactory.createInternalTenantContext(context));
+    }
+
+    @Override
+    public List<PaymentMethod> searchPaymentMethods(final String searchKey, final String pluginName, final TenantContext context) throws PaymentApiException {
+        return methodProcessor.searchPaymentMethods(searchKey, pluginName, internalCallContextFactory.createInternalTenantContext(context));
+    }
+
+    @Override
     public void deletedPaymentMethod(final Account account, final UUID paymentMethodId, final boolean deleteDefaultPaymentMethodWithAutoPayOff, final CallContext context)
             throws PaymentApiException {
         methodProcessor.deletedPaymentMethod(account, paymentMethodId, deleteDefaultPaymentMethodWithAutoPayOff, internalCallContextFactory.createInternalCallContext(account.getId(), context));
diff --git a/payment/src/main/java/com/ning/billing/payment/core/PaymentMethodProcessor.java b/payment/src/main/java/com/ning/billing/payment/core/PaymentMethodProcessor.java
index 2318459..c72e410 100644
--- a/payment/src/main/java/com/ning/billing/payment/core/PaymentMethodProcessor.java
+++ b/payment/src/main/java/com/ning/billing/payment/core/PaymentMethodProcessor.java
@@ -18,6 +18,7 @@ package com.ning.billing.payment.core;
 
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Set;
 import java.util.UUID;
@@ -32,6 +33,7 @@ import com.ning.billing.ErrorCode;
 import com.ning.billing.account.api.Account;
 import com.ning.billing.account.api.AccountApiException;
 import com.ning.billing.bus.api.PersistentBus;
+import com.ning.billing.commons.locker.GlobalLocker;
 import com.ning.billing.osgi.api.OSGIServiceRegistration;
 import com.ning.billing.payment.api.DefaultPaymentMethod;
 import com.ning.billing.payment.api.PaymentApiException;
@@ -48,7 +50,7 @@ import com.ning.billing.payment.provider.DefaultPaymentMethodInfoPlugin;
 import com.ning.billing.payment.provider.ExternalPaymentProviderPlugin;
 import com.ning.billing.util.callcontext.InternalCallContext;
 import com.ning.billing.util.callcontext.InternalTenantContext;
-import com.ning.billing.util.globallocker.GlobalLocker;
+import com.ning.billing.util.dao.NonEntityDao;
 import com.ning.billing.util.svcapi.account.AccountInternalApi;
 import com.ning.billing.util.svcapi.invoice.InvoiceInternalApi;
 import com.ning.billing.util.svcapi.tag.TagInternalApi;
@@ -71,10 +73,11 @@ public class PaymentMethodProcessor extends ProcessorBase {
                                   final InvoiceInternalApi invoiceApi,
                                   final PersistentBus eventBus,
                                   final PaymentDao paymentDao,
+                                  final NonEntityDao nonEntityDao,
                                   final TagInternalApi tagUserApi,
                                   final GlobalLocker locker,
                                   @Named(PLUGIN_EXECUTOR_NAMED) final ExecutorService executor) {
-        super(pluginRegistry, accountInternalApi, eventBus, paymentDao, tagUserApi, locker, executor, invoiceApi);
+        super(pluginRegistry, accountInternalApi, eventBus, paymentDao, nonEntityDao, tagUserApi, locker, executor, invoiceApi);
     }
 
     public Set<String> getAvailablePlugins() {
@@ -138,7 +141,7 @@ public class PaymentMethodProcessor extends ProcessorBase {
         if (withPluginInfo) {
             try {
                 final PaymentPluginApi pluginApi = getPaymentPluginApi(paymentMethodModelDao.getPluginName());
-                paymentMethodPlugin = pluginApi.getPaymentMethodDetail(paymentMethodModelDao.getAccountId(), paymentMethodModelDao.getId(), context.toTenantContext());
+                paymentMethodPlugin = pluginApi.getPaymentMethodDetail(paymentMethodModelDao.getAccountId(), paymentMethodModelDao.getId(), buildTenantContext(context));
             } catch (PaymentPluginApiException e) {
                 log.warn("Error retrieving payment method " + paymentMethodModelDao.getId() + " from plugin " + paymentMethodModelDao.getPluginName(), e);
                 throw new PaymentApiException(ErrorCode.PAYMENT_GET_PAYMENT_METHODS, paymentMethodModelDao.getAccountId(), paymentMethodModelDao.getId());
@@ -150,6 +153,45 @@ public class PaymentMethodProcessor extends ProcessorBase {
         return new DefaultPaymentMethod(paymentMethodModelDao, paymentMethodPlugin);
     }
 
+    public List<PaymentMethod> searchPaymentMethods(final String searchKey, final InternalTenantContext internalTenantContext) {
+        final List<PaymentMethod> results = new LinkedList<PaymentMethod>();
+
+        // Search in all plugins
+        for (final String pluginName : getAvailablePlugins()) {
+            try {
+                results.addAll(searchPaymentMethods(searchKey, pluginName, internalTenantContext));
+            } catch (PaymentApiException e) {
+                log.warn("Error while searching plugin " + pluginName, e);
+                // Non-fatal, continue to search other plugins
+            }
+        }
+
+        return results;
+    }
+
+    public List<PaymentMethod> searchPaymentMethods(final String searchKey, final String pluginName, final InternalTenantContext internalTenantContext) throws PaymentApiException {
+        final PaymentPluginApi pluginApi = getPaymentPluginApi(pluginName);
+        final List<PaymentMethodPlugin> paymentMethods;
+        try {
+            paymentMethods = pluginApi.searchPaymentMethods(searchKey, buildTenantContext(internalTenantContext));
+        } catch (PaymentPluginApiException e) {
+            throw new PaymentApiException(e, ErrorCode.PAYMENT_PLUGIN_SEARCH_PAYMENT_METHODS, pluginName, searchKey);
+        }
+
+        final List<PaymentMethod> results = new LinkedList<PaymentMethod>();
+        for (final PaymentMethodPlugin paymentMethodPlugin : paymentMethods) {
+            final PaymentMethodModelDao paymentMethodModelDao = paymentDao.getPaymentMethodIncludedDeleted(paymentMethodPlugin.getKbPaymentMethodId(), internalTenantContext);
+            if (paymentMethodModelDao == null) {
+                log.warn("Unable to find payment method id " + paymentMethodPlugin.getKbPaymentMethodId() + " present in plugin " + pluginName);
+                continue;
+            }
+
+            results.add(new DefaultPaymentMethod(paymentMethodModelDao, paymentMethodPlugin));
+        }
+
+        return results;
+    }
+
     public PaymentMethod getExternalPaymentMethod(final Account account, final InternalTenantContext context) throws PaymentApiException {
         final List<PaymentMethod> paymentMethods = getPaymentMethods(account, false, context);
         for (final PaymentMethod paymentMethod : paymentMethods) {
diff --git a/payment/src/main/java/com/ning/billing/payment/core/PaymentProcessor.java b/payment/src/main/java/com/ning/billing/payment/core/PaymentProcessor.java
index 5d79fb9..81ea1b5 100644
--- a/payment/src/main/java/com/ning/billing/payment/core/PaymentProcessor.java
+++ b/payment/src/main/java/com/ning/billing/payment/core/PaymentProcessor.java
@@ -20,10 +20,12 @@ import com.google.common.base.Predicate;
 import com.google.common.collect.Collections2;
 import com.google.inject.name.Named;
 import com.ning.billing.ErrorCode;
+import com.ning.billing.ObjectType;
 import com.ning.billing.account.api.Account;
 import com.ning.billing.account.api.AccountApiException;
 import com.ning.billing.bus.api.PersistentBus;
 import com.ning.billing.clock.Clock;
+import com.ning.billing.commons.locker.GlobalLocker;
 import com.ning.billing.invoice.api.Invoice;
 import com.ning.billing.invoice.api.InvoiceApiException;
 import com.ning.billing.osgi.api.OSGIServiceRegistration;
@@ -47,10 +49,11 @@ import com.ning.billing.payment.retry.FailedPaymentRetryService.FailedPaymentRet
 import com.ning.billing.payment.retry.PluginFailureRetryService.PluginFailureRetryServiceScheduler;
 import com.ning.billing.util.callcontext.InternalCallContext;
 import com.ning.billing.util.callcontext.InternalTenantContext;
+import com.ning.billing.util.callcontext.TenantContext;
 import com.ning.billing.util.config.PaymentConfig;
+import com.ning.billing.util.dao.NonEntityDao;
 import com.ning.billing.util.events.BusInternalEvent;
 import com.ning.billing.util.events.PaymentErrorInternalEvent;
-import com.ning.billing.util.globallocker.GlobalLocker;
 import com.ning.billing.util.svcapi.account.AccountInternalApi;
 import com.ning.billing.util.svcapi.invoice.InvoiceInternalApi;
 import com.ning.billing.util.svcapi.tag.TagInternalApi;
@@ -99,12 +102,13 @@ public class PaymentProcessor extends ProcessorBase {
                             final PluginFailureRetryServiceScheduler pluginFailureRetryService,
                             final AutoPayRetryServiceScheduler autoPayoffRetryService,
                             final PaymentDao paymentDao,
+                            final NonEntityDao nonEntityDao,
                             final PersistentBus eventBus,
                             final Clock clock,
                             final GlobalLocker locker,
                             final PaymentConfig paymentConfig,
                             @Named(PLUGIN_EXECUTOR_NAMED) final ExecutorService executor) {
-        super(pluginRegistry, accountUserApi, eventBus, paymentDao, tagUserApi, locker, executor, invoiceApi);
+        super(pluginRegistry, accountUserApi, eventBus, paymentDao, nonEntityDao, tagUserApi, locker, executor, invoiceApi);
         this.paymentMethodProcessor = paymentMethodProcessor;
         this.failedPaymentRetryService = failedPaymentRetryService;
         this.pluginFailureRetryService = pluginFailureRetryService;
@@ -125,7 +129,7 @@ public class PaymentProcessor extends ProcessorBase {
         PaymentInfoPlugin pluginInfo = null;
         if (plugin != null) {
             try {
-                pluginInfo = plugin.getPaymentInfo(model.getAccountId(), paymentId, context.toTenantContext());
+                pluginInfo = plugin.getPaymentInfo(model.getAccountId(), paymentId, buildTenantContext(context));
             } catch (PaymentPluginApiException e) {
                 throw new PaymentApiException(ErrorCode.PAYMENT_PLUGIN_GET_PAYMENT_INFO, paymentId, e.toString());
             }
@@ -133,7 +137,6 @@ public class PaymentProcessor extends ProcessorBase {
         return fromPaymentModelDao(model, pluginInfo, context);
     }
 
-
     public List<Payment> getInvoicePayments(final UUID invoiceId, final InternalTenantContext context) {
         return getPayments(paymentDao.getPaymentsForInvoice(invoiceId, context), context);
     }
diff --git a/payment/src/main/java/com/ning/billing/payment/core/ProcessorBase.java b/payment/src/main/java/com/ning/billing/payment/core/ProcessorBase.java
index 3f5ea77..2b67354 100644
--- a/payment/src/main/java/com/ning/billing/payment/core/ProcessorBase.java
+++ b/payment/src/main/java/com/ning/billing/payment/core/ProcessorBase.java
@@ -31,6 +31,9 @@ import com.ning.billing.ObjectType;
 import com.ning.billing.account.api.Account;
 import com.ning.billing.bus.api.PersistentBus;
 import com.ning.billing.bus.api.PersistentBus.EventBusException;
+import com.ning.billing.commons.locker.GlobalLock;
+import com.ning.billing.commons.locker.GlobalLocker;
+import com.ning.billing.commons.locker.LockFailedException;
 import com.ning.billing.invoice.api.Invoice;
 import com.ning.billing.invoice.api.InvoiceApiException;
 import com.ning.billing.osgi.api.OSGIServiceRegistration;
@@ -41,11 +44,10 @@ import com.ning.billing.payment.plugin.api.PaymentPluginApi;
 import com.ning.billing.util.api.TagApiException;
 import com.ning.billing.util.callcontext.InternalCallContext;
 import com.ning.billing.util.callcontext.InternalTenantContext;
+import com.ning.billing.util.callcontext.TenantContext;
+import com.ning.billing.util.dao.NonEntityDao;
 import com.ning.billing.util.events.BusInternalEvent;
-import com.ning.billing.util.globallocker.GlobalLock;
-import com.ning.billing.util.globallocker.GlobalLocker;
-import com.ning.billing.util.globallocker.GlobalLocker.LockerType;
-import com.ning.billing.util.globallocker.LockFailedException;
+import com.ning.billing.util.globallocker.LockerType;
 import com.ning.billing.util.svcapi.account.AccountInternalApi;
 import com.ning.billing.util.svcapi.invoice.InvoiceInternalApi;
 import com.ning.billing.util.svcapi.tag.TagInternalApi;
@@ -65,6 +67,7 @@ public abstract class ProcessorBase {
     protected final GlobalLocker locker;
     protected final ExecutorService executor;
     protected final PaymentDao paymentDao;
+    protected final NonEntityDao nonEntityDao;
     protected final TagInternalApi tagInternalApi;
 
     private static final Logger log = LoggerFactory.getLogger(ProcessorBase.class);
@@ -74,6 +77,7 @@ public abstract class ProcessorBase {
                          final AccountInternalApi accountInternalApi,
                          final PersistentBus eventBus,
                          final PaymentDao paymentDao,
+                         final NonEntityDao nonEntityDao,
                          final TagInternalApi tagInternalApi,
                          final GlobalLocker locker,
                          final ExecutorService executor, final InvoiceInternalApi invoiceApi) {
@@ -81,6 +85,7 @@ public abstract class ProcessorBase {
         this.accountInternalApi = accountInternalApi;
         this.eventBus = eventBus;
         this.paymentDao = paymentDao;
+        this.nonEntityDao = nonEntityDao;
         this.locker = locker;
         this.executor = executor;
         this.tagInternalApi = tagInternalApi;
@@ -150,6 +155,10 @@ public abstract class ProcessorBase {
         return invoice;
     }
 
+    protected TenantContext buildTenantContext(final InternalTenantContext context) {
+        return context.toTenantContext(nonEntityDao.retrieveIdFromObject(context.getTenantRecordId(), ObjectType.TENANT));
+    }
+
     public interface WithAccountLockCallback<T> {
 
         public T doOperation() throws PaymentApiException;
@@ -181,7 +190,7 @@ public abstract class ProcessorBase {
                 throws PaymentApiException {
             GlobalLock lock = null;
             try {
-                lock = locker.lockWithNumberOfTries(LockerType.ACCOUNT_FOR_INVOICE_PAYMENTS, accountExternalKey, NB_LOCK_TRY);
+                lock = locker.lockWithNumberOfTries(LockerType.ACCOUNT_FOR_INVOICE_PAYMENTS.toString(), accountExternalKey, NB_LOCK_TRY);
                 return callback.doOperation();
             } catch (LockFailedException e) {
                 final String format = String.format("Failed to lock account %s", accountExternalKey);
diff --git a/payment/src/main/java/com/ning/billing/payment/core/RefundProcessor.java b/payment/src/main/java/com/ning/billing/payment/core/RefundProcessor.java
index 2a47887..413a9c5 100644
--- a/payment/src/main/java/com/ning/billing/payment/core/RefundProcessor.java
+++ b/payment/src/main/java/com/ning/billing/payment/core/RefundProcessor.java
@@ -36,6 +36,7 @@ import com.ning.billing.ObjectType;
 import com.ning.billing.account.api.Account;
 import com.ning.billing.account.api.AccountApiException;
 import com.ning.billing.bus.api.PersistentBus;
+import com.ning.billing.commons.locker.GlobalLocker;
 import com.ning.billing.invoice.api.InvoiceApiException;
 import com.ning.billing.invoice.api.InvoiceItem;
 import com.ning.billing.osgi.api.OSGIServiceRegistration;
@@ -55,7 +56,7 @@ import com.ning.billing.util.callcontext.InternalCallContext;
 import com.ning.billing.util.callcontext.InternalCallContextFactory;
 import com.ning.billing.util.callcontext.InternalTenantContext;
 import com.ning.billing.util.callcontext.UserType;
-import com.ning.billing.util.globallocker.GlobalLocker;
+import com.ning.billing.util.dao.NonEntityDao;
 import com.ning.billing.util.svcapi.account.AccountInternalApi;
 import com.ning.billing.util.svcapi.invoice.InvoiceInternalApi;
 import com.ning.billing.util.svcapi.tag.TagInternalApi;
@@ -83,9 +84,10 @@ public class RefundProcessor extends ProcessorBase {
                            final InternalCallContextFactory internalCallContextFactory,
                            final TagInternalApi tagUserApi,
                            final PaymentDao paymentDao,
+                           final NonEntityDao nonEntityDao,
                            final GlobalLocker locker,
                            @Named(PLUGIN_EXECUTOR_NAMED) final ExecutorService executor) {
-        super(pluginRegistry, accountApi, eventBus, paymentDao, tagUserApi, locker, executor, invoiceApi);
+        super(pluginRegistry, accountApi, eventBus, paymentDao, nonEntityDao, tagUserApi, locker, executor, invoiceApi);
         this.internalCallContextFactory = internalCallContextFactory;
     }
 
diff --git a/payment/src/main/java/com/ning/billing/payment/provider/DefaultNoOpPaymentMethodPlugin.java b/payment/src/main/java/com/ning/billing/payment/provider/DefaultNoOpPaymentMethodPlugin.java
index 89fc2d1..d431522 100644
--- a/payment/src/main/java/com/ning/billing/payment/provider/DefaultNoOpPaymentMethodPlugin.java
+++ b/payment/src/main/java/com/ning/billing/payment/provider/DefaultNoOpPaymentMethodPlugin.java
@@ -24,24 +24,33 @@ import com.ning.billing.payment.api.PaymentMethodPlugin;
 
 public class DefaultNoOpPaymentMethodPlugin implements PaymentMethodPlugin {
 
+    private final UUID kbPaymentMethodId;
     private final String externalId;
     private final boolean isDefault;
     private List<PaymentMethodKVInfo> props;
 
-    public DefaultNoOpPaymentMethodPlugin(final PaymentMethodPlugin src) {
+    public DefaultNoOpPaymentMethodPlugin(final UUID kbPaymentMethodId, final PaymentMethodPlugin src) {
+        this.kbPaymentMethodId = kbPaymentMethodId;
         this.externalId = UUID.randomUUID().toString();
         this.isDefault = src.isDefaultPaymentMethod();
         this.props = src.getProperties();
     }
 
-    public DefaultNoOpPaymentMethodPlugin(final String externalId, final boolean isDefault,
+    public DefaultNoOpPaymentMethodPlugin(final String externalId,
+                                          final boolean isDefault,
                                           final List<PaymentMethodKVInfo> props) {
+        this.kbPaymentMethodId = null;
         this.externalId = externalId;
         this.isDefault = isDefault;
         this.props = props;
     }
 
     @Override
+    public UUID getKbPaymentMethodId() {
+        return kbPaymentMethodId;
+    }
+
+    @Override
     public String getExternalPaymentMethodId() {
         return externalId;
     }
diff --git a/payment/src/main/java/com/ning/billing/payment/provider/DefaultNoOpPaymentProviderPlugin.java b/payment/src/main/java/com/ning/billing/payment/provider/DefaultNoOpPaymentProviderPlugin.java
index 7d23d9e..449324a 100644
--- a/payment/src/main/java/com/ning/billing/payment/provider/DefaultNoOpPaymentProviderPlugin.java
+++ b/payment/src/main/java/com/ning/billing/payment/provider/DefaultNoOpPaymentProviderPlugin.java
@@ -37,7 +37,9 @@ import com.ning.billing.util.callcontext.CallContext;
 import com.ning.billing.util.callcontext.TenantContext;
 import com.ning.billing.clock.Clock;
 
+import com.google.common.base.Predicate;
 import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
 import com.google.common.collect.LinkedListMultimap;
 import com.google.common.collect.Multimap;
 import com.google.inject.Inject;
@@ -108,7 +110,7 @@ public class DefaultNoOpPaymentProviderPlugin implements NoOpPaymentPluginApi {
 
     @Override
     public void addPaymentMethod(final UUID kbAccountId, final UUID kbPaymentMethodId, final PaymentMethodPlugin paymentMethodProps, final boolean setDefault, final CallContext context) throws PaymentPluginApiException {
-        final PaymentMethodPlugin realWithID = new DefaultNoOpPaymentMethodPlugin(paymentMethodProps);
+        final PaymentMethodPlugin realWithID = new DefaultNoOpPaymentMethodPlugin(kbPaymentMethodId, paymentMethodProps);
         List<PaymentMethodPlugin> pms = paymentMethods.get(kbPaymentMethodId.toString());
         if (pms == null) {
             pms = new LinkedList<PaymentMethodPlugin>();
@@ -155,8 +157,19 @@ public class DefaultNoOpPaymentProviderPlugin implements NoOpPaymentPluginApi {
     }
 
     @Override
-    public List<PaymentMethodPlugin> searchPaymentMethods(final String s, final TenantContext tenantContext) throws PaymentPluginApiException {
-        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    public List<PaymentMethodPlugin> searchPaymentMethods(final String searchKey, final TenantContext tenantContext) throws PaymentPluginApiException {
+        return ImmutableList.<PaymentMethodPlugin>copyOf(Iterables.<PaymentMethodPlugin>filter(Iterables.<PaymentMethodPlugin>concat(paymentMethods.values()), new Predicate<PaymentMethodPlugin>() {
+            @Override
+            public boolean apply(final PaymentMethodPlugin input) {
+                return (input.getAddress1() != null && input.getAddress1().contains(searchKey)) ||
+                       (input.getAddress2() != null && input.getAddress2().contains(searchKey)) ||
+                       (input.getCCLast4() != null && input.getCCLast4().contains(searchKey)) ||
+                       (input.getCCName() != null && input.getCCName().contains(searchKey)) ||
+                       (input.getCity() != null && input.getCity().contains(searchKey)) ||
+                       (input.getState() != null && input.getState().contains(searchKey)) ||
+                       (input.getCountry() != null && input.getCountry().contains(searchKey));
+            }
+        }));
     }
 
     @Override
diff --git a/payment/src/main/java/com/ning/billing/payment/provider/ExternalPaymentProviderPlugin.java b/payment/src/main/java/com/ning/billing/payment/provider/ExternalPaymentProviderPlugin.java
index c8ed58a..b1b6915 100644
--- a/payment/src/main/java/com/ning/billing/payment/provider/ExternalPaymentProviderPlugin.java
+++ b/payment/src/main/java/com/ning/billing/payment/provider/ExternalPaymentProviderPlugin.java
@@ -22,6 +22,7 @@ import java.util.List;
 import java.util.UUID;
 
 import com.ning.billing.catalog.api.Currency;
+import com.ning.billing.clock.Clock;
 import com.ning.billing.payment.api.PaymentMethodKVInfo;
 import com.ning.billing.payment.api.PaymentMethodPlugin;
 import com.ning.billing.payment.plugin.api.PaymentInfoPlugin;
@@ -33,8 +34,8 @@ import com.ning.billing.payment.plugin.api.RefundInfoPlugin;
 import com.ning.billing.payment.plugin.api.RefundPluginStatus;
 import com.ning.billing.util.callcontext.CallContext;
 import com.ning.billing.util.callcontext.TenantContext;
-import com.ning.billing.clock.Clock;
 
+import com.google.common.collect.ImmutableList;
 import com.google.inject.Inject;
 
 /**
@@ -84,7 +85,7 @@ public class ExternalPaymentProviderPlugin implements PaymentPluginApi {
 
     @Override
     public PaymentMethodPlugin getPaymentMethodDetail(final UUID kbAccountId, final UUID kbPaymentMethodId, final TenantContext context) throws PaymentPluginApiException {
-        return new DefaultNoOpPaymentMethodPlugin("unknow", false, Collections.<PaymentMethodKVInfo>emptyList());
+        return new DefaultNoOpPaymentMethodPlugin("unknown", false, Collections.<PaymentMethodKVInfo>emptyList());
     }
 
     @Override
@@ -93,12 +94,12 @@ public class ExternalPaymentProviderPlugin implements PaymentPluginApi {
 
     @Override
     public List<PaymentMethodInfoPlugin> getPaymentMethods(final UUID kbAccountId, final boolean refreshFromGateway, final CallContext context) throws PaymentPluginApiException {
-        return null;
+        return ImmutableList.<PaymentMethodInfoPlugin>of();
     }
 
     @Override
     public List<PaymentMethodPlugin> searchPaymentMethods(final String s, final TenantContext tenantContext) throws PaymentPluginApiException {
-        return null;  //To change body of implemented methods use File | Settings | File Templates.
+        return ImmutableList.<PaymentMethodPlugin>of();
     }
 
     @Override
diff --git a/payment/src/test/java/com/ning/billing/payment/api/TestPaymentMethodPlugin.java b/payment/src/test/java/com/ning/billing/payment/api/TestPaymentMethodPlugin.java
index d0ae14b..76d28e1 100644
--- a/payment/src/test/java/com/ning/billing/payment/api/TestPaymentMethodPlugin.java
+++ b/payment/src/test/java/com/ning/billing/payment/api/TestPaymentMethodPlugin.java
@@ -17,20 +17,28 @@
 package com.ning.billing.payment.api;
 
 import java.util.List;
+import java.util.UUID;
 
 public class TestPaymentMethodPlugin extends TestPaymentMethodPluginBase implements PaymentMethodPlugin {
 
+    private final UUID kbPaymentMethodId;
     private final String externalPaymentMethodId;
     private final boolean isDefaultPaymentMethod;
     private final List<PaymentMethodKVInfo> properties;
 
-    public TestPaymentMethodPlugin(final PaymentMethodPlugin src, final String externalPaymentId) {
+    public TestPaymentMethodPlugin(final UUID kbPaymentMethodId, final PaymentMethodPlugin src, final String externalPaymentId) {
+        this.kbPaymentMethodId = kbPaymentMethodId;
         this.externalPaymentMethodId = externalPaymentId;
         this.isDefaultPaymentMethod = src.isDefaultPaymentMethod();
         this.properties = src.getProperties();
     }
 
     @Override
+    public UUID getKbPaymentMethodId() {
+        return kbPaymentMethodId;
+    }
+
+    @Override
     public String getExternalPaymentMethodId() {
         return externalPaymentMethodId;
     }
@@ -44,5 +52,4 @@ public class TestPaymentMethodPlugin extends TestPaymentMethodPluginBase impleme
     public List<PaymentMethodKVInfo> getProperties() {
         return properties;
     }
-
 }
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 2da363f..3768b18 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
@@ -25,20 +25,22 @@ import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.atomic.AtomicBoolean;
 
 import com.ning.billing.catalog.api.Currency;
-import com.ning.billing.payment.api.TestPaymentMethodPlugin;
+import com.ning.billing.clock.Clock;
 import com.ning.billing.payment.api.PaymentMethodPlugin;
+import com.ning.billing.payment.api.TestPaymentMethodPlugin;
 import com.ning.billing.payment.plugin.api.NoOpPaymentPluginApi;
 import com.ning.billing.payment.plugin.api.PaymentInfoPlugin;
-import com.ning.billing.payment.plugin.api.PaymentPluginStatus;
 import com.ning.billing.payment.plugin.api.PaymentMethodInfoPlugin;
 import com.ning.billing.payment.plugin.api.PaymentPluginApiException;
+import com.ning.billing.payment.plugin.api.PaymentPluginStatus;
 import com.ning.billing.payment.plugin.api.RefundInfoPlugin;
 import com.ning.billing.payment.plugin.api.RefundPluginStatus;
 import com.ning.billing.util.callcontext.CallContext;
 import com.ning.billing.util.callcontext.TenantContext;
-import com.ning.billing.clock.Clock;
 
+import com.google.common.base.Predicate;
 import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
 import com.google.common.collect.LinkedListMultimap;
 import com.google.common.collect.Multimap;
 import com.google.inject.Inject;
@@ -116,7 +118,7 @@ public class MockPaymentProviderPlugin implements NoOpPaymentPluginApi {
     @Override
     public void addPaymentMethod(final UUID kbAccountId, final UUID kbPaymentMethodId, final PaymentMethodPlugin paymentMethodProps, final boolean setDefault, final CallContext context) throws PaymentPluginApiException {
         // externalPaymentMethodId is set to a random value
-        final PaymentMethodPlugin realWithID = new TestPaymentMethodPlugin(paymentMethodProps, UUID.randomUUID().toString());
+        final PaymentMethodPlugin realWithID = new TestPaymentMethodPlugin(kbPaymentMethodId, paymentMethodProps, UUID.randomUUID().toString());
         paymentMethods.put(kbPaymentMethodId.toString(), realWithID);
 
         final PaymentMethodInfoPlugin realInfoWithID = new DefaultPaymentMethodInfoPlugin(kbAccountId, kbPaymentMethodId, setDefault, UUID.randomUUID().toString());
@@ -144,8 +146,19 @@ public class MockPaymentProviderPlugin implements NoOpPaymentPluginApi {
     }
 
     @Override
-    public List<PaymentMethodPlugin> searchPaymentMethods(final String s, final TenantContext tenantContext) throws PaymentPluginApiException {
-        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    public List<PaymentMethodPlugin> searchPaymentMethods(final String searchKey, final TenantContext tenantContext) throws PaymentPluginApiException {
+        return ImmutableList.<PaymentMethodPlugin>copyOf(Iterables.<PaymentMethodPlugin>filter(paymentMethods.values(), new Predicate<PaymentMethodPlugin>() {
+            @Override
+            public boolean apply(final PaymentMethodPlugin input) {
+                return (input.getAddress1() != null && input.getAddress1().contains(searchKey)) ||
+                       (input.getAddress2() != null && input.getAddress2().contains(searchKey)) ||
+                       (input.getCCLast4() != null && input.getCCLast4().contains(searchKey)) ||
+                       (input.getCCName() != null && input.getCCName().contains(searchKey)) ||
+                       (input.getCity() != null && input.getCity().contains(searchKey)) ||
+                       (input.getState() != null && input.getState().contains(searchKey)) ||
+                       (input.getCountry() != null && input.getCountry().contains(searchKey));
+            }
+        }));
     }
 
     @Override

pom.xml 4(+2 -2)

diff --git a/pom.xml b/pom.xml
index 3b542b3..ffc3084 100644
--- a/pom.xml
+++ b/pom.xml
@@ -19,10 +19,10 @@
     <parent>
         <artifactId>killbill-oss-parent</artifactId>
         <groupId>com.ning.billing</groupId>
-        <version>0.3.5-SNAPSHOT</version>
+        <version>0.4.0-SNAPSHOT</version>
     </parent>
     <artifactId>killbill</artifactId>
-    <version>0.3.6-SNAPSHOT</version>
+    <version>0.5.1-SNAPSHOT</version>
     <packaging>pom</packaging>
     <name>killbill</name>
     <description>Library for managing recurring subscriptions and the associated billing</description>

README.md 63(+1 -62)

diff --git a/README.md b/README.md
index e965ce1..442e402 100644
--- a/README.md
+++ b/README.md
@@ -1,65 +1,4 @@
 [![Build Status](https://travis-ci.org/killbill/killbill.png)](https://travis-ci.org/killbill/killbill)
 
 Killbill is an open source subscription management/billing system.
-You can find the documentation [here](http://ning.github.com/killbill/).
-
-Setting up your own tenant
---------------------------
-
-Killbill supports multiple tenants running on the same server. Each tenant needs to identify itself when using the /1.0
-API via HTTP Basic authentication.
-
-For example, trying to access all tag definitions without being authenticated would throw a 400 error:
-
-    ~> curl -v http://127.0.0.1:8080/1.0/kb/tagDefinitions
-    * About to connect() to 127.0.0.1 port 8080 (#0)
-    *   Trying 127.0.0.1... connected
-    * Connected to 127.0.0.1 (127.0.0.1) port 8080 (#0)
-    > GET /1.0/kb/tagDefinitions HTTP/1.1
-    > User-Agent: curl/7.21.4 (universal-apple-darwin11.0) libcurl/7.21.4 OpenSSL/0.9.8r zlib/1.2.5
-    > Host: 127.0.0.1:8080
-    > Accept: */*
-    >
-    < HTTP/1.1 401 Unauthorized
-    < WWW-Authenticate: BASIC realm="application"
-    < Content-Length: 0
-    < Server: Jetty(8.1.2.v20120308)
-    <
-    * Connection #0 to host 127.0.0.1 left intact
-    * Closing connection #0
-
-
-Before you can use the /1.0 API, you need to create your own tenant. To do so, post your username (`apiKey`) and password
-(`apiSecret`) to the `/1.0/kb/tenants` endpoint (the header `X-Killbill-CreatedBy` is used for auditing purposes).
-For example, to create the a tenant with the credentials bob/lazar:
-
-    ~> curl -v -XPOST \
-               -H'Content-Type: application/json' \
-               -H'X-Killbill-CreatedBy: admin' \
-               -d'{"apiKey": "bob", "apiSecret": "lazar"}' \
-               http://127.0.0.1:8080/1.0/kb/tenants
-    * About to connect() to 127.0.0.1 port 8080 (#0)
-    *   Trying 127.0.0.1... connected
-    * Connected to 127.0.0.1 (127.0.0.1) port 8080 (#0)
-    > POST /1.0/kb/tenants HTTP/1.1
-    > User-Agent: curl/7.21.4 (universal-apple-darwin11.0) libcurl/7.21.4 OpenSSL/0.9.8r zlib/1.2.5
-    > Host: 127.0.0.1:8080
-    > Accept: */*
-    > Content-Type: application/json
-    > X-Killbill-CreatedBy: admin
-    > Content-Length: 39
-    >
-    < HTTP/1.1 201 Created
-    < Location: http://127.0.0.1:8080/1.0/kb/tenants/f07bc7d5-00e8-48bd-8b43-ef8537219171
-    < Content-Type: application/json
-    < Transfer-Encoding: chunked
-    < Server: Jetty(8.1.2.v20120308)
-    <
-    * Connection #0 to host 127.0.0.1 left intact
-    * Closing connection #0
-    {"uri":"/1.0/kb/tenants/f07bc7d5-00e8-48bd-8b43-ef8537219171"}
-
-
-You can now access the API using basic auth, e.g.:
-
-    ~> curl -v http://127.0.0.1:8080/1.0/kb/tagDefinitions -ubob:lazar
+You can find the documentation [here](http://kill-bill.org).
diff --git a/server/killbill-server.iml b/server/killbill-server.iml
index 57c99eb..6d9a7bc 100644
--- a/server/killbill-server.iml
+++ b/server/killbill-server.iml
@@ -12,6 +12,23 @@
     </content>
     <orderEntry type="inheritedJdk" />
     <orderEntry type="sourceFolder" forTests="false" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-payment:0.3.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-clock:0.1.7" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-queue:0.1.7" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-jdbi:0.1.7" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-notification:0.3.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.shiro:shiro-core:1.2.1" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-beatrix:test-jar:tests:0.3.6-SNAPSHOT" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-payment:test-jar:tests:0.3.6-SNAPSHOT" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-util:test-jar:tests:0.3.6-SNAPSHOT" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing.commons:killbill-clock:test-jar:tests:0.1.7" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.shiro:shiro-web:1.2.1" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing:killbill-api:0.6.0-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-payment:0.4.0-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-notification:0.4.0-SNAPSHOT" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-beatrix:test-jar:tests:0.5.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-payment:test-jar:tests:0.5.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-util:test-jar:tests:0.5.1-SNAPSHOT" level="project" />
     <orderEntry type="library" scope="RUNTIME" name="Maven: ch.qos.logback:logback-classic:1.0.1" level="project" />
     <orderEntry type="library" scope="RUNTIME" name="Maven: ch.qos.logback:logback-core:1.0.1" level="project" />
     <orderEntry type="library" name="Maven: org.slf4j:slf4j-api:1.7.5" level="project" />
@@ -28,10 +45,10 @@
     <orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-annotations:2.1.0" level="project" />
     <orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-databind:2.1.0" level="project" />
     <orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-core:2.1.0" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing:killbill-api:0.3.3-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing:killbill-api:0.6.0-SNAPSHOT" level="project" />
     <orderEntry type="library" name="Maven: joda-time:joda-time:2.0" level="project" />
     <orderEntry type="module" module-name="killbill-internal-api" />
-    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-payment:0.3.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-payment:0.4.0-SNAPSHOT" level="project" />
     <orderEntry type="library" name="Maven: org.skife.config:config-magic:0.14" level="project" />
     <orderEntry type="module" module-name="killbill-util" />
     <orderEntry type="library" name="Maven: com.fasterxml.jackson.dataformat:jackson-dataformat-csv:2.1.0" level="project" />
@@ -39,13 +56,14 @@
     <orderEntry type="library" name="Maven: com.jolbox:bonecp:0.7.1.RELEASE" level="project" />
     <orderEntry type="library" name="Maven: com.mchange:c3p0:0.9.2" level="project" />
     <orderEntry type="library" name="Maven: com.mchange:mchange-commons-java:0.2.3.3" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-clock:0.1.7" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-queue:0.1.7" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-jdbi:0.1.7" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-clock:0.2.1" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-locker:0.2.1" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-queue:0.2.1" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-jdbi:0.2.1" level="project" />
     <orderEntry type="library" name="Maven: org.jdbi:jdbi:2.39.1" level="project" />
     <orderEntry type="library" name="Maven: com.yammer.metrics:metrics-core:2.1.2" level="project" />
     <orderEntry type="library" name="Maven: org.weakref:jmxutils:1.12" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-notification:0.3.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-notification:0.4.0-SNAPSHOT" level="project" />
     <orderEntry type="library" name="Maven: com.samskivert:jmustache:1.5" level="project" />
     <orderEntry type="library" name="Maven: net.sf.ehcache:ehcache-core:2.6.2" level="project" />
     <orderEntry type="library" scope="RUNTIME" name="Maven: org.antlr:stringtemplate:3.2.1" level="project" />
@@ -53,6 +71,11 @@
     <orderEntry type="library" name="Maven: org.apache.commons:commons-email:1.2" level="project" />
     <orderEntry type="library" name="Maven: javax.mail:mail:1.4.1" level="project" />
     <orderEntry type="library" name="Maven: javax.activation:activation:1.1" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.shiro:shiro-core:1.2.2" level="project" />
+    <orderEntry type="library" name="Maven: commons-beanutils:commons-beanutils:1.8.3" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.shiro:shiro-ehcache:1.2.2" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.shiro:shiro-guice:1.2.2" level="project" />
+    <orderEntry type="library" scope="RUNTIME" name="Maven: org.slf4j:jcl-over-slf4j:1.7.5" level="project" />
     <orderEntry type="module" module-name="killbill-beatrix" />
     <orderEntry type="module" module-name="killbill-catalog" />
     <orderEntry type="module" module-name="killbill-entitlement" />
@@ -62,12 +85,10 @@
     <orderEntry type="module" module-name="killbill-payment" />
     <orderEntry type="module" module-name="killbill-subscription" />
     <orderEntry type="module" module-name="killbill-tenant" />
-    <orderEntry type="library" name="Maven: org.apache.shiro:shiro-core:1.2.1" level="project" />
-    <orderEntry type="library" name="Maven: commons-beanutils:commons-beanutils:1.8.3" level="project" />
     <orderEntry type="module" module-name="killbill-usage" />
     <orderEntry type="library" name="Maven: commons-io:commons-io:2.1" level="project" />
     <orderEntry type="module" module-name="killbill-beatrix" scope="TEST" production-on-test="" />
-    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-beatrix:test-jar:tests:0.3.6-SNAPSHOT" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-beatrix:test-jar:tests:0.5.1-SNAPSHOT" level="project" />
     <orderEntry type="module" module-name="killbill-jaxrs" />
     <orderEntry type="library" name="Maven: javax.ws.rs:jsr311-api:1.1.1" level="project" />
     <orderEntry type="module" module-name="killbill-osgi" />
@@ -79,10 +100,11 @@
     <orderEntry type="library" name="Maven: org.apache.felix:org.osgi.core:1.0.1" level="project" />
     <orderEntry type="module" module-name="killbill-overdue" />
     <orderEntry type="module" module-name="killbill-payment" scope="TEST" production-on-test="" />
-    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-payment:test-jar:tests:0.3.6-SNAPSHOT" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-payment:test-jar:tests:0.5.1-SNAPSHOT" level="project" />
     <orderEntry type="module" module-name="killbill-util" scope="TEST" production-on-test="" />
-    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-util:test-jar:tests:0.3.6-SNAPSHOT" level="project" />
-    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing.commons:killbill-clock:test-jar:tests:0.1.7" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-util:test-jar:tests:0.5.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing.commons:killbill-clock:test-jar:tests:0.2.1" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing.commons:killbill-embeddeddb:0.2.1" level="project" />
     <orderEntry type="library" name="Maven: com.ning.jetty:ning-service-skeleton-base:0.1.7" level="project" />
     <orderEntry type="library" name="Maven: com.ning:metrics.eventtracker-smile:4.1.2" level="project" />
     <orderEntry type="library" name="Maven: com.fasterxml.jackson.dataformat:jackson-dataformat-smile:2.0.1" level="project" />
@@ -104,7 +126,6 @@
     <orderEntry type="library" name="Maven: commons-lang:commons-lang:2.6" level="project" />
     <orderEntry type="library" name="Maven: com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:2.0.0" level="project" />
     <orderEntry type="library" name="Maven: com.fasterxml.jackson.module:jackson-module-jaxb-annotations:2.0.0" level="project" />
-    <orderEntry type="library" scope="RUNTIME" name="Maven: org.slf4j:jcl-over-slf4j:1.7.5" level="project" />
     <orderEntry type="library" name="Maven: org.slf4j:jul-to-slf4j:1.7.5" level="project" />
     <orderEntry type="library" name="Maven: com.ning.jetty:ning-service-skeleton-eventtracker:0.1.7" level="project" />
     <orderEntry type="library" name="Maven: com.ning.jetty:ning-service-skeleton-utils:0.1.7" level="project" />
@@ -119,7 +140,7 @@
     <orderEntry type="library" scope="PROVIDED" name="Maven: javax.servlet:javax.servlet-api:3.0.1" level="project" />
     <orderEntry type="library" scope="TEST" name="Maven: mysql:mysql-connector-mxj:5.0.12" level="project" />
     <orderEntry type="library" scope="TEST" name="Maven: mysql:mysql-connector-mxj-db-files:5.0.12" level="project" />
-    <orderEntry type="library" name="Maven: org.apache.shiro:shiro-web:1.2.1" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.shiro:shiro-web:1.2.2" level="project" />
     <orderEntry type="library" scope="TEST" name="Maven: org.eclipse.jetty:jetty-deploy:8.1.11.v20130520" level="project" />
     <orderEntry type="library" scope="TEST" name="Maven: org.eclipse.jetty:jetty-webapp:8.1.11.v20130520" level="project" />
     <orderEntry type="library" scope="TEST" name="Maven: org.eclipse.jetty:jetty-xml:8.1.11.v20130520" level="project" />

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

diff --git a/server/pom.xml b/server/pom.xml
index dda7b64..931c4e6 100644
--- a/server/pom.xml
+++ b/server/pom.xml
@@ -19,7 +19,7 @@
     <parent>
         <artifactId>killbill</artifactId>
         <groupId>com.ning.billing</groupId>
-        <version>0.3.6-SNAPSHOT</version>
+        <version>0.5.1-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <artifactId>killbill-server</artifactId>
@@ -153,6 +153,11 @@
         </dependency>
         <dependency>
             <groupId>com.ning.billing.commons</groupId>
+            <artifactId>killbill-embeddeddb</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.ning.billing.commons</groupId>
             <artifactId>killbill-queue</artifactId>
         </dependency>
         <dependency>
diff --git a/server/src/main/java/com/ning/billing/server/listeners/KillbillGuiceListener.java b/server/src/main/java/com/ning/billing/server/listeners/KillbillGuiceListener.java
index 6337238..4ac7aa2 100644
--- a/server/src/main/java/com/ning/billing/server/listeners/KillbillGuiceListener.java
+++ b/server/src/main/java/com/ning/billing/server/listeners/KillbillGuiceListener.java
@@ -19,6 +19,7 @@ package com.ning.billing.server.listeners;
 import java.lang.management.ManagementFactory;
 
 import javax.management.MBeanServer;
+import javax.servlet.ServletContext;
 import javax.servlet.ServletContextEvent;
 
 import org.slf4j.Logger;
@@ -53,8 +54,8 @@ public class KillbillGuiceListener extends SetupServer {
     private BusService killbillBusService;
     private KillbillEventHandler killbilleventHandler;
 
-    protected Module getModule() {
-        return new KillbillServerModule();
+    protected Module getModule(final ServletContext servletContext) {
+        return new KillbillServerModule(servletContext);
     }
 
     private void registerMBeansForCache(final CacheManager cacheManager) {
@@ -66,7 +67,7 @@ public class KillbillGuiceListener extends SetupServer {
 
     @Override
     public void contextInitialized(final ServletContextEvent event) {
-        final boolean multitenant = Boolean.parseBoolean(System.getProperty(KILLBILL_MULTITENANT_PROPERTY, "false"));
+        final boolean multitenant = Boolean.parseBoolean(System.getProperty(KILLBILL_MULTITENANT_PROPERTY, "true"));
 
         final ServerModuleBuilder builder = new ServerModuleBuilder()
                 .addConfig(KillbillServerConfig.class)
@@ -74,7 +75,7 @@ public class KillbillGuiceListener extends SetupServer {
                 .addJMXExport(KillbillHealthcheck.class)
                 .addJMXExport(NotificationQueueService.class)
                 .addJMXExport(PersistentBus.class)
-                .addModule(getModule())
+                .addModule(getModule(event.getServletContext()))
                         // Don't filter all requests through Jersey, only the JAX-RS APIs (otherwise,
                         // things like static resources, favicon, etc. are 404'ed)
                 .setJerseyUriPattern("(" + JaxRsResourceBase.PREFIX + "|" + JaxRsResourceBase.PLUGINS_PATH + ")" + "/.*")
diff --git a/server/src/main/java/com/ning/billing/server/modules/DataSourceProvider.java b/server/src/main/java/com/ning/billing/server/modules/DataSourceProvider.java
new file mode 100644
index 0000000..9e9547a
--- /dev/null
+++ b/server/src/main/java/com/ning/billing/server/modules/DataSourceProvider.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright 2010-2013 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.server.modules;
+
+import java.util.concurrent.TimeUnit;
+
+import javax.inject.Inject;
+import javax.inject.Provider;
+import javax.sql.DataSource;
+
+import org.skife.config.TimeSpan;
+
+import com.ning.jetty.jdbi.config.DaoConfig;
+
+import com.jolbox.bonecp.BoneCPConfig;
+import com.jolbox.bonecp.BoneCPDataSource;
+import com.mchange.v2.c3p0.ComboPooledDataSource;
+
+public class DataSourceProvider implements Provider<DataSource> {
+
+    private final DaoConfig config;
+
+    @Inject
+    public DataSourceProvider(final DaoConfig config) {
+        this.config = config;
+    }
+
+    @Override
+    public DataSource get() {
+        return getDataSource();
+    }
+
+    private DataSource getDataSource() {
+        final DataSource ds;
+
+        // TODO PIERRE DaoConfig is in the skeleton
+        final String dataSource = System.getProperty("com.ning.jetty.jdbi.datasource", "c3p0");
+        if (dataSource.equals("c3p0")) {
+            ds = getC3P0DataSource();
+        } else if (dataSource.equals("bonecp")) {
+            ds = getBoneCPDatSource();
+        } else {
+            throw new IllegalArgumentException("DataSource " + dataSource + " unsupported");
+        }
+
+        return ds;
+    }
+
+    private DataSource getBoneCPDatSource() {
+        final BoneCPConfig dbConfig = new BoneCPConfig();
+        dbConfig.setJdbcUrl(config.getJdbcUrl());
+        dbConfig.setUsername(config.getUsername());
+        dbConfig.setPassword(config.getPassword());
+        dbConfig.setMinConnectionsPerPartition(config.getMinIdle());
+        dbConfig.setMaxConnectionsPerPartition(config.getMaxActive());
+        dbConfig.setConnectionTimeout(config.getConnectionTimeout().getPeriod(), config.getConnectionTimeout().getUnit());
+        dbConfig.setIdleMaxAge(config.getIdleMaxAge().getPeriod(), config.getIdleMaxAge().getUnit());
+        dbConfig.setMaxConnectionAge(config.getMaxConnectionAge().getPeriod(), config.getMaxConnectionAge().getUnit());
+        dbConfig.setIdleConnectionTestPeriod(config.getIdleConnectionTestPeriod().getPeriod(), config.getIdleConnectionTestPeriod().getUnit());
+        dbConfig.setPartitionCount(1);
+        dbConfig.setDisableJMX(false);
+
+        return new BoneCPDataSource(dbConfig);
+    }
+
+    private DataSource getC3P0DataSource() {
+        final ComboPooledDataSource cpds = new ComboPooledDataSource();
+        cpds.setJdbcUrl(config.getJdbcUrl());
+        cpds.setUser(config.getUsername());
+        cpds.setPassword(config.getPassword());
+        // http://www.mchange.com/projects/c3p0/#minPoolSize
+        // Minimum number of Connections a pool will maintain at any given time.
+        cpds.setMinPoolSize(config.getMinIdle());
+        // http://www.mchange.com/projects/c3p0/#maxPoolSize
+        // Maximum number of Connections a pool will maintain at any given time.
+        cpds.setMaxPoolSize(config.getMaxActive());
+        // http://www.mchange.com/projects/c3p0/#checkoutTimeout
+        // The number of milliseconds a client calling getConnection() will wait for a Connection to be checked-in or
+        // acquired when the pool is exhausted. Zero means wait indefinitely. Setting any positive value will cause the getConnection()
+        // call to time-out and break with an SQLException after the specified number of milliseconds.
+        cpds.setCheckoutTimeout(toMilliSeconds(config.getConnectionTimeout()));
+        // http://www.mchange.com/projects/c3p0/#maxIdleTime
+        // Seconds a Connection can remain pooled but unused before being discarded. Zero means idle connections never expire.
+        cpds.setMaxIdleTime(toSeconds(config.getIdleMaxAge()));
+        // http://www.mchange.com/projects/c3p0/#maxConnectionAge
+        // Seconds, effectively a time to live. A Connection older than maxConnectionAge will be destroyed and purged from the pool.
+        // This differs from maxIdleTime in that it refers to absolute age. Even a Connection which has not been much idle will be purged
+        // from the pool if it exceeds maxConnectionAge. Zero means no maximum absolute age is enforced.
+        cpds.setMaxConnectionAge(toSeconds(config.getMaxConnectionAge()));
+        // http://www.mchange.com/projects/c3p0/#idleConnectionTestPeriod
+        // If this is a number greater than 0, c3p0 will test all idle, pooled but unchecked-out connections, every this number of seconds.
+        cpds.setIdleConnectionTestPeriod(toSeconds(config.getIdleConnectionTestPeriod()));
+
+        return cpds;
+    }
+
+    private int toSeconds(final TimeSpan timeSpan) {
+        return toSeconds(timeSpan.getPeriod(), timeSpan.getUnit());
+    }
+
+    private int toSeconds(final long period, final TimeUnit timeUnit) {
+        return (int) TimeUnit.SECONDS.convert(period, timeUnit);
+    }
+
+    private int toMilliSeconds(final TimeSpan timeSpan) {
+        return toMilliSeconds(timeSpan.getPeriod(), timeSpan.getUnit());
+    }
+
+    private int toMilliSeconds(final long period, final TimeUnit timeUnit) {
+        return (int) TimeUnit.MILLISECONDS.convert(period, timeUnit);
+    }
+}
diff --git a/server/src/main/java/com/ning/billing/server/modules/DBIProvider.java b/server/src/main/java/com/ning/billing/server/modules/DBIProvider.java
index 66c5cdf..81d747f 100644
--- a/server/src/main/java/com/ning/billing/server/modules/DBIProvider.java
+++ b/server/src/main/java/com/ning/billing/server/modules/DBIProvider.java
@@ -20,7 +20,6 @@ import java.util.concurrent.TimeUnit;
 
 import javax.sql.DataSource;
 
-import org.skife.config.TimeSpan;
 import org.skife.jdbi.v2.DBI;
 import org.skife.jdbi.v2.TimingCollector;
 import org.skife.jdbi.v2.tweak.SQLLog;
@@ -38,9 +37,6 @@ import com.ning.jetty.jdbi.config.DaoConfig;
 
 import com.google.inject.Inject;
 import com.google.inject.Provider;
-import com.jolbox.bonecp.BoneCPConfig;
-import com.jolbox.bonecp.BoneCPDataSource;
-import com.mchange.v2.c3p0.ComboPooledDataSource;
 import com.yammer.metrics.core.MetricsRegistry;
 import com.yammer.metrics.jdbi.InstrumentedTimingCollector;
 import com.yammer.metrics.jdbi.strategies.BasicSqlNameStrategy;
@@ -49,12 +45,14 @@ public class DBIProvider implements Provider<DBI> {
 
     private static final Logger logger = LoggerFactory.getLogger(DBIProvider.class);
 
+    private final DataSource ds;
     private final MetricsRegistry metricsRegistry;
     private final DaoConfig config;
     private SQLLog sqlLog;
 
     @Inject
-    public DBIProvider(final MetricsRegistry metricsRegistry, final DaoConfig config) {
+    public DBIProvider(final DataSource ds, final MetricsRegistry metricsRegistry, final DaoConfig config) {
+        this.ds = ds;
         this.metricsRegistry = metricsRegistry;
         this.config = config;
     }
@@ -66,8 +64,6 @@ public class DBIProvider implements Provider<DBI> {
 
     @Override
     public DBI get() {
-        final DataSource ds = getDataSource();
-
         final DBI dbi = new DBI(ds);
         dbi.registerArgumentFactory(new UUIDArgumentFactory());
         dbi.registerArgumentFactory(new DateTimeZoneArgumentFactory());
@@ -95,84 +91,4 @@ public class DBIProvider implements Provider<DBI> {
 
         return dbi;
     }
-
-    private DataSource getDataSource() {
-        final DataSource ds;
-
-        // TODO PIERRE DaoConfig is in the skeleton
-        final String dataSource = System.getProperty("com.ning.jetty.jdbi.datasource", "c3p0");
-        if (dataSource.equals("c3p0")) {
-            ds = getC3P0DataSource();
-        } else if (dataSource.equals("bonecp")) {
-            ds = getBoneCPDatSource();
-        } else {
-            throw new IllegalArgumentException("DataSource " + dataSource + " unsupported");
-        }
-
-        return ds;
-    }
-
-    private DataSource getBoneCPDatSource() {
-        final BoneCPConfig dbConfig = new BoneCPConfig();
-        dbConfig.setJdbcUrl(config.getJdbcUrl());
-        dbConfig.setUsername(config.getUsername());
-        dbConfig.setPassword(config.getPassword());
-        dbConfig.setMinConnectionsPerPartition(config.getMinIdle());
-        dbConfig.setMaxConnectionsPerPartition(config.getMaxActive());
-        dbConfig.setConnectionTimeout(config.getConnectionTimeout().getPeriod(), config.getConnectionTimeout().getUnit());
-        dbConfig.setIdleMaxAge(config.getIdleMaxAge().getPeriod(), config.getIdleMaxAge().getUnit());
-        dbConfig.setMaxConnectionAge(config.getMaxConnectionAge().getPeriod(), config.getMaxConnectionAge().getUnit());
-        dbConfig.setIdleConnectionTestPeriod(config.getIdleConnectionTestPeriod().getPeriod(), config.getIdleConnectionTestPeriod().getUnit());
-        dbConfig.setPartitionCount(1);
-        dbConfig.setDisableJMX(false);
-
-        return new BoneCPDataSource(dbConfig);
-    }
-
-    private DataSource getC3P0DataSource() {
-        final ComboPooledDataSource cpds = new ComboPooledDataSource();
-        cpds.setJdbcUrl(config.getJdbcUrl());
-        cpds.setUser(config.getUsername());
-        cpds.setPassword(config.getPassword());
-        // http://www.mchange.com/projects/c3p0/#minPoolSize
-        // Minimum number of Connections a pool will maintain at any given time.
-        cpds.setMinPoolSize(config.getMinIdle());
-        // http://www.mchange.com/projects/c3p0/#maxPoolSize
-        // Maximum number of Connections a pool will maintain at any given time.
-        cpds.setMaxPoolSize(config.getMaxActive());
-        // http://www.mchange.com/projects/c3p0/#checkoutTimeout
-        // The number of milliseconds a client calling getConnection() will wait for a Connection to be checked-in or
-        // acquired when the pool is exhausted. Zero means wait indefinitely. Setting any positive value will cause the getConnection()
-        // call to time-out and break with an SQLException after the specified number of milliseconds.
-        cpds.setCheckoutTimeout(toMilliSeconds(config.getConnectionTimeout()));
-        // http://www.mchange.com/projects/c3p0/#maxIdleTime
-        // Seconds a Connection can remain pooled but unused before being discarded. Zero means idle connections never expire.
-        cpds.setMaxIdleTime(toSeconds(config.getIdleMaxAge()));
-        // http://www.mchange.com/projects/c3p0/#maxConnectionAge
-        // Seconds, effectively a time to live. A Connection older than maxConnectionAge will be destroyed and purged from the pool.
-        // This differs from maxIdleTime in that it refers to absolute age. Even a Connection which has not been much idle will be purged
-        // from the pool if it exceeds maxConnectionAge. Zero means no maximum absolute age is enforced.
-        cpds.setMaxConnectionAge(toSeconds(config.getMaxConnectionAge()));
-        // http://www.mchange.com/projects/c3p0/#idleConnectionTestPeriod
-        // If this is a number greater than 0, c3p0 will test all idle, pooled but unchecked-out connections, every this number of seconds.
-        cpds.setIdleConnectionTestPeriod(toSeconds(config.getIdleConnectionTestPeriod()));
-
-        return cpds;
-    }
-
-    private int toSeconds(final TimeSpan timeSpan) {
-        return toSeconds(timeSpan.getPeriod(), timeSpan.getUnit());
-    }
-
-    private int toSeconds(final long period, final TimeUnit timeUnit) {
-        return (int) TimeUnit.SECONDS.convert(period, timeUnit);
-    }
-
-    private int toMilliSeconds(final TimeSpan timeSpan) {
-        return toMilliSeconds(timeSpan.getPeriod(), timeSpan.getUnit());
-    }
-
-    private int toMilliSeconds(final long period, final TimeUnit timeUnit) {
-        return (int) TimeUnit.MILLISECONDS.convert(period, timeUnit);
-    }
 }
diff --git a/server/src/main/java/com/ning/billing/server/modules/KillbillServerModule.java b/server/src/main/java/com/ning/billing/server/modules/KillbillServerModule.java
index a0c63e0..8113fdc 100644
--- a/server/src/main/java/com/ning/billing/server/modules/KillbillServerModule.java
+++ b/server/src/main/java/com/ning/billing/server/modules/KillbillServerModule.java
@@ -16,6 +16,9 @@
 
 package com.ning.billing.server.modules;
 
+import javax.servlet.ServletContext;
+import javax.sql.DataSource;
+
 import com.ning.billing.entitlement.glue.DefaultEntitlementModule;
 import org.skife.config.ConfigSource;
 import org.skife.config.SimplePropertyConfigSource;
@@ -61,15 +64,24 @@ import com.ning.billing.util.glue.ClockModule;
 import com.ning.billing.util.glue.CustomFieldModule;
 import com.ning.billing.util.glue.ExportModule;
 import com.ning.billing.util.glue.GlobalLockerModule;
+import com.ning.billing.util.glue.KillBillShiroAopModule;
+import com.ning.billing.util.glue.KillBillShiroModule;
 import com.ning.billing.util.glue.NonEntityDaoModule;
 import com.ning.billing.util.glue.NotificationQueueModule;
 import com.ning.billing.util.glue.RecordIdModule;
+import com.ning.billing.util.glue.SecurityModule;
 import com.ning.billing.util.glue.TagStoreModule;
 
 import com.google.inject.AbstractModule;
 
 public class KillbillServerModule extends AbstractModule {
 
+    protected final ServletContext servletContext;
+
+    public KillbillServerModule(final ServletContext servletContext) {
+        this.servletContext = servletContext;
+    }
+
     @Override
     protected void configure() {
         configureDao();
@@ -90,6 +102,7 @@ public class KillbillServerModule extends AbstractModule {
         } catch (final Exception ignore) {
         }
         bind(IDBI.class).to(DBI.class).asEagerSingleton();
+        bind(DataSource.class).toProvider(DataSourceProvider.class).asEagerSingleton();
         bind(DBI.class).toProvider(DBIProvider.class).asEagerSingleton();
     }
 
@@ -145,6 +158,9 @@ public class KillbillServerModule extends AbstractModule {
         install(new DefaultOSGIModule(configSource));
         install(new UsageModule(configSource));
         install(new RecordIdModule());
+        install(new KillBillShiroWebModule(servletContext));
+        install(new KillBillShiroAopModule());
+        install(new SecurityModule());
 
         installClock();
     }
diff --git a/server/src/main/java/com/ning/billing/server/modules/KillBillShiroWebModule.java b/server/src/main/java/com/ning/billing/server/modules/KillBillShiroWebModule.java
new file mode 100644
index 0000000..0dfade8
--- /dev/null
+++ b/server/src/main/java/com/ning/billing/server/modules/KillBillShiroWebModule.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2010-2013 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.server.modules;
+
+import javax.servlet.ServletContext;
+
+import org.apache.shiro.cache.CacheManager;
+import org.apache.shiro.guice.web.ShiroWebModule;
+import org.apache.shiro.session.mgt.SessionManager;
+import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
+
+import com.ning.billing.jaxrs.resources.JaxrsResource;
+import com.ning.billing.util.glue.EhCacheManagerProvider;
+import com.ning.billing.util.glue.IniRealmProvider;
+import com.ning.billing.util.glue.JDBCSessionDaoProvider;
+import com.ning.billing.util.glue.KillBillShiroModule;
+import com.ning.billing.util.security.shiro.dao.JDBCSessionDao;
+import com.ning.billing.util.security.shiro.realm.KillBillJndiLdapRealm;
+
+import com.google.inject.binder.AnnotatedBindingBuilder;
+
+// For Kill Bill server only.
+// See com.ning.billing.util.glue.KillBillShiroModule for Kill Bill library.
+public class KillBillShiroWebModule extends ShiroWebModule {
+
+    public KillBillShiroWebModule(final ServletContext servletContext) {
+        super(servletContext);
+    }
+
+    @Override
+    protected void configureShiroWeb() {
+        bindRealm().toProvider(IniRealmProvider.class).asEagerSingleton();
+
+        if (KillBillShiroModule.isLDAPEnabled()) {
+            bindRealm().to(KillBillJndiLdapRealm.class).asEagerSingleton();
+        }
+
+        // Magic provider to configure the cache manager
+        bind(CacheManager.class).toProvider(EhCacheManagerProvider.class).asEagerSingleton();
+
+        if (KillBillShiroModule.isRBACEnabled()) {
+            addFilterChain(JaxrsResource.PREFIX + "/**", AUTHC_BASIC);
+        }
+    }
+
+    @Override
+    protected void bindSessionManager(final AnnotatedBindingBuilder<SessionManager> bind) {
+        // Bypass the servlet container completely for session management and delegate it to Shiro.
+        // The default session timeout is 30 minutes.
+        bind.to(DefaultWebSessionManager.class).asEagerSingleton();
+
+        // Magic provider to configure the session DAO
+        bind(JDBCSessionDao.class).toProvider(JDBCSessionDaoProvider.class).asEagerSingleton();
+    }
+}
diff --git a/server/src/main/java/com/ning/billing/server/security/TenantFilter.java b/server/src/main/java/com/ning/billing/server/security/TenantFilter.java
index 98a77aa..2eaa1a4 100644
--- a/server/src/main/java/com/ning/billing/server/security/TenantFilter.java
+++ b/server/src/main/java/com/ning/billing/server/security/TenantFilter.java
@@ -26,20 +26,28 @@ import javax.servlet.FilterConfig;
 import javax.servlet.ServletException;
 import javax.servlet.ServletRequest;
 import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
 
-import org.apache.shiro.SecurityUtils;
-import org.apache.shiro.subject.Subject;
+import org.apache.shiro.authc.AuthenticationException;
+import org.apache.shiro.authc.AuthenticationToken;
+import org.apache.shiro.authc.UsernamePasswordToken;
+import org.apache.shiro.authc.pam.ModularRealmAuthenticator;
+import org.apache.shiro.realm.Realm;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.ning.billing.jaxrs.resources.JaxrsResource;
 import com.ning.billing.tenant.api.Tenant;
 import com.ning.billing.tenant.api.TenantApiException;
 import com.ning.billing.tenant.api.TenantUserApi;
 
+import com.google.common.collect.ImmutableList;
+
 @Singleton
 public class TenantFilter implements Filter {
 
-    public static final String SUBJECT = "killbill_subject";
+    // See com.ning.billing.jaxrs.util.Context
     public static final String TENANT = "killbill_tenant";
 
     private static final Logger log = LoggerFactory.getLogger(TenantFilter.class);
@@ -47,23 +55,55 @@ public class TenantFilter implements Filter {
     @Inject
     private TenantUserApi tenantUserApi;
 
+    private final ModularRealmAuthenticator modularRealmAuthenticator;
+
+    public TenantFilter() {
+        final Realm killbillJdbcRealm = new KillbillJdbcRealm();
+
+        // We use Shiro to verify the api credentials - but the Shiro Subject is only used for RBAC
+        modularRealmAuthenticator = new ModularRealmAuthenticator();
+        modularRealmAuthenticator.setRealms(ImmutableList.<Realm>of(killbillJdbcRealm));
+    }
+
     @Override
     public void init(final FilterConfig filterConfig) throws ServletException {
     }
 
     @Override
     public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain) throws IOException, ServletException {
-        final Subject subject = SecurityUtils.getSubject();
-        request.setAttribute(SUBJECT, subject);
-
-        final String apiKey = (String) subject.getPrincipal();
-        if (apiKey == null) {
-            // Resource not protected by Shiro?
+        if (shouldSkipFilter(request)) {
             chain.doFilter(request, response);
             return;
         }
 
+        // Lookup tenant information in the headers
+        String apiKey = null;
+        String apiSecret = null;
+        if (request instanceof HttpServletRequest) {
+            final HttpServletRequest httpServletRequest = (HttpServletRequest) request;
+            apiKey = httpServletRequest.getHeader(JaxrsResource.HDR_API_KEY);
+            apiSecret = httpServletRequest.getHeader(JaxrsResource.HDR_API_SECRET);
+        }
+
+        // Multi-tenancy is enabled if this filter is installed, we can't continue without credentials
+        if (apiKey == null || apiSecret == null) {
+            final String errorMessage = String.format("Make sure to set the %s and %s headers", JaxrsResource.HDR_API_KEY, JaxrsResource.HDR_API_SECRET);
+            sendAuthError(response, errorMessage);
+            return;
+        }
+
+        // Verify the apiKey/apiSecret combo
+        final AuthenticationToken token = new UsernamePasswordToken(apiKey, apiSecret);
         try {
+            modularRealmAuthenticator.authenticate(token);
+        } catch (AuthenticationException e) {
+            final String errorMessage = e.getLocalizedMessage();
+            sendAuthError(response, errorMessage);
+            return;
+        }
+
+        try {
+            // Load the tenant in the request object (apiKey is unique across tenants)
             final Tenant tenant = tenantUserApi.getTenantByApiKey(apiKey);
             request.setAttribute(TENANT, tenant);
 
@@ -77,4 +117,26 @@ public class TenantFilter implements Filter {
     @Override
     public void destroy() {
     }
+
+    private boolean shouldSkipFilter(final ServletRequest request) {
+        boolean shouldSkip = false;
+
+        // Chicken - egg problem
+        if (request instanceof HttpServletRequest) {
+            final HttpServletRequest httpServletRequest = (HttpServletRequest) request;
+            final String path = httpServletRequest.getRequestURI();
+            if ("/1.0/kb/tenants".equals(path) && "POST".equals(httpServletRequest.getMethod())) {
+                shouldSkip = true;
+            }
+        }
+
+        return shouldSkip;
+    }
+
+    private void sendAuthError(final ServletResponse response, final String errorMessage) throws IOException {
+        if (response instanceof HttpServletResponse) {
+            final HttpServletResponse httpServletResponse = (HttpServletResponse) response;
+            httpServletResponse.sendError(401, errorMessage);
+        }
+    }
 }
diff --git a/server/src/main/resources/shiro.ini b/server/src/main/resources/shiro.ini
new file mode 100644
index 0000000..a419d0a
--- /dev/null
+++ b/server/src/main/resources/shiro.ini
@@ -0,0 +1,29 @@
+###################################################################################
+#                                                                                 #
+#                   Copyright 2010-2013 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.                                                         #
+#                                                                                 #
+###################################################################################
+
+# [main]
+# See com.ning.billing.util.glue.KillBillShiroModule
+# Use -Dkillbill.server.rbac=false to disable RBAC
+
+# Default admin user
+# Use -Dkillbill.security.shiroResourcePath=/var/tmp/shiro.ini to specify your own config
+[users]
+admin = password, root
+
+[roles]
+root = *:*
diff --git a/server/src/main/webapp/WEB-INF/web.xml b/server/src/main/webapp/WEB-INF/web.xml
index 13d7694..482e6c1 100644
--- a/server/src/main/webapp/WEB-INF/web.xml
+++ b/server/src/main/webapp/WEB-INF/web.xml
@@ -20,17 +20,13 @@
         xmlns="http://java.sun.com/xml/ns/javaee"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
         version="2.5">
-    <listener>
-        <!-- Initialize Shiro WebEnvironment and put it into the ServletContext -->
-        <listener-class>org.apache.shiro.web.env.EnvironmentLoaderListener</listener-class>
-    </listener>
     <filter>
         <!-- Filter all requests through Shiro -->
         <filter-name>ShiroFilter</filter-name>
         <filter-class>org.apache.shiro.web.servlet.ShiroFilter</filter-class>
     </filter>
     <filter-mapping>
-        <!-- The Shitor filter-mapping should come first -->
+        <!-- The Shiro filter-mapping should come first -->
         <filter-name>ShiroFilter</filter-name>
         <url-pattern>/*</url-pattern>
         <dispatcher>REQUEST</dispatcher>
diff --git a/server/src/test/java/com/ning/billing/jaxrs/KillbillClient.java b/server/src/test/java/com/ning/billing/jaxrs/KillbillClient.java
index 0f8ce60..04d8012 100644
--- a/server/src/test/java/com/ning/billing/jaxrs/KillbillClient.java
+++ b/server/src/test/java/com/ning/billing/jaxrs/KillbillClient.java
@@ -44,6 +44,7 @@ import com.ning.billing.catalog.api.ProductCategory;
 import com.ning.billing.jaxrs.json.AccountEmailJson;
 import com.ning.billing.jaxrs.json.AccountJson;
 import com.ning.billing.jaxrs.json.AccountTimelineJson;
+import com.ning.billing.jaxrs.json.CatalogJsonSimple;
 import com.ning.billing.jaxrs.json.ChargebackJson;
 import com.ning.billing.jaxrs.json.CreditJson;
 import com.ning.billing.jaxrs.json.EntitlementJsonNoEvents;
@@ -56,6 +57,7 @@ import com.ning.billing.jaxrs.json.PaymentJsonWithBundleKeys;
 import com.ning.billing.jaxrs.json.PaymentMethodJson;
 import com.ning.billing.jaxrs.json.PaymentMethodJson.PaymentMethodPluginDetailJson;
 import com.ning.billing.jaxrs.json.PaymentMethodJson.PaymentMethodProperties;
+import com.ning.billing.jaxrs.json.PlanDetailJson;
 import com.ning.billing.jaxrs.json.RefundJson;
 import com.ning.billing.jaxrs.json.TenantJson;
 import com.ning.billing.jaxrs.resources.JaxrsResource;
@@ -64,6 +66,8 @@ import com.ning.http.client.AsyncCompletionHandler;
 import com.ning.http.client.AsyncHttpClient;
 import com.ning.http.client.AsyncHttpClient.BoundRequestBuilder;
 import com.ning.http.client.ListenableFuture;
+import com.ning.http.client.Realm;
+import com.ning.http.client.Realm.AuthScheme;
 import com.ning.http.client.Response;
 import com.ning.jetty.core.CoreConfig;
 
@@ -72,9 +76,12 @@ import com.fasterxml.jackson.databind.ObjectMapper;
 import com.google.common.base.Function;
 import com.google.common.collect.Collections2;
 import com.google.common.collect.ImmutableMap;
+import com.google.inject.TypeLiteral;
 
 import static com.ning.billing.jaxrs.resources.JaxrsResource.ACCOUNTS;
 import static com.ning.billing.jaxrs.resources.JaxrsResource.BUNDLES;
+import static com.ning.billing.jaxrs.resources.JaxrsResource.HDR_API_KEY;
+import static com.ning.billing.jaxrs.resources.JaxrsResource.HDR_API_SECRET;
 import static com.ning.billing.jaxrs.resources.JaxrsResource.QUERY_DELETE_DEFAULT_PM_WITH_AUTO_PAY_OFF;
 import static com.ning.billing.jaxrs.resources.JaxrsResource.SUBSCRIPTIONS;
 import static org.testng.Assert.assertEquals;
@@ -84,7 +91,7 @@ public abstract class KillbillClient extends GuicyKillbillTestSuiteWithEmbeddedD
 
     protected static final String PLUGIN_NAME = "noop";
 
-    protected static final int DEFAULT_HTTP_TIMEOUT_SEC = 50000;
+    protected static final int DEFAULT_HTTP_TIMEOUT_SEC = 20;
 
     protected static final Map<String, String> DEFAULT_EMPTY_QUERY = new HashMap<String, String>();
 
@@ -99,6 +106,16 @@ public abstract class KillbillClient extends GuicyKillbillTestSuiteWithEmbeddedD
     protected AsyncHttpClient httpClient;
     protected ObjectMapper mapper;
 
+    // Multi-Tenancy information, if enabled
+    protected String DEFAULT_API_KEY = UUID.randomUUID().toString();
+    protected String DEFAULT_API_SECRET = UUID.randomUUID().toString();
+    protected String apiKey = DEFAULT_API_KEY;
+    protected String apiSecret = DEFAULT_API_SECRET;
+
+    // RBAC information, if enabled
+    protected String username = null;
+    protected String password = null;
+
     // Context information to be passed around
     protected static final String createdBy = "Toto";
     protected static final String reason = "i am god";
@@ -154,6 +171,44 @@ public abstract class KillbillClient extends GuicyKillbillTestSuiteWithEmbeddedD
     }
 
     //
+    // SECURITY UTILITIES
+    //
+
+    protected void loginAsAdmin() {
+        loginAs("tester", "tester");
+    }
+
+    protected void loginAs(final String username, final String password) {
+        this.username = username;
+        this.password = password;
+    }
+
+    protected void logout() {
+        this.username = null;
+        this.password = null;
+    }
+
+    protected List<String> getPermissions(@Nullable final String username, @Nullable final String password) throws Exception {
+        final String oldUsername = this.username;
+        final String oldPassword = this.password;
+
+        this.username = username;
+        this.password = password;
+
+        final Response response = doGet(JaxrsResource.SECURITY_PATH + "/permissions", DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
+        Assert.assertEquals(response.getStatusCode(), Status.OK.getStatusCode());
+
+        this.username = oldUsername;
+        this.password = oldPassword;
+
+        final String baseJson = response.getResponseBody();
+        final List<String> objFromJson = mapper.readValue(baseJson, new TypeReference<List<String>>() {});
+        Assert.assertNotNull(objFromJson);
+
+        return objFromJson;
+    }
+
+    //
     // ACCOUNT UTILITIES
     //
 
@@ -180,6 +235,18 @@ public abstract class KillbillClient extends GuicyKillbillTestSuiteWithEmbeddedD
         return objFromJson;
     }
 
+    protected List<AccountJson> searchAccountsByKey(final String key) throws Exception {
+        final String uri = JaxrsResource.ACCOUNTS_PATH + "/" + JaxrsResource.SEARCH + "/" + key;
+        final Response response = doGet(uri, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
+        Assert.assertEquals(response.getStatusCode(), Status.OK.getStatusCode());
+
+        final String baseJson = response.getResponseBody();
+        final List<AccountJson> objFromJson = mapper.readValue(baseJson, new TypeReference<List<AccountJson>>() {});
+        Assert.assertNotNull(objFromJson);
+
+        return objFromJson;
+    }
+
     protected Response getAccountByExternalKeyNoValidation(final String externalKey) {
         final Map<String, String> queryParams = new HashMap<String, String>();
         queryParams.put(JaxrsResource.QUERY_EXTERNAL_KEY, externalKey);
@@ -372,6 +439,10 @@ public abstract class KillbillClient extends GuicyKillbillTestSuiteWithEmbeddedD
         return doGetInvoice(invoiceId, Boolean.FALSE, InvoiceJsonSimple.class);
     }
 
+    protected InvoiceJsonSimple getInvoice(final Integer invoiceNumber) throws IOException {
+        return getInvoice(invoiceNumber.toString());
+    }
+
     protected InvoiceJsonWithItems getInvoiceWithItems(final String invoiceId) throws IOException {
         return doGetInvoice(invoiceId, Boolean.TRUE, InvoiceJsonWithItems.class);
     }
@@ -543,8 +614,9 @@ public abstract class KillbillClient extends GuicyKillbillTestSuiteWithEmbeddedD
     protected PaymentMethodJson getPaymentMethodWithPluginInfo(final String paymentMethodId) throws IOException {
         final String paymentMethodURI = JaxrsResource.PAYMENT_METHODS_PATH + "/" + paymentMethodId;
 
-        final Map<String, String> queryPaymentMethods = new HashMap<String, String>();
-        final Response paymentMethodResponse = doGet(paymentMethodURI, queryPaymentMethods, DEFAULT_HTTP_TIMEOUT_SEC);
+        final Response paymentMethodResponse = doGet(paymentMethodURI,
+                                                     ImmutableMap.<String, String>of(JaxrsResource.QUERY_PAYMENT_METHOD_PLUGIN_INFO, "true"),
+                                                     DEFAULT_HTTP_TIMEOUT_SEC);
         assertEquals(paymentMethodResponse.getStatusCode(), Status.OK.getStatusCode());
 
         final PaymentMethodJson paymentMethodJson = mapper.readValue(paymentMethodResponse.getResponseBody(), PaymentMethodJson.class);
@@ -553,6 +625,24 @@ public abstract class KillbillClient extends GuicyKillbillTestSuiteWithEmbeddedD
         return paymentMethodJson;
     }
 
+    protected List<PaymentMethodJson> searchPaymentMethodsByKey(final String key) throws Exception {
+        return searchPaymentMethodsByKeyAndPlugin(key, null);
+    }
+
+    protected List<PaymentMethodJson> searchPaymentMethodsByKeyAndPlugin(final String key, @Nullable final String pluginName) throws Exception {
+        final String uri = JaxrsResource.PAYMENT_METHODS_PATH + "/" + JaxrsResource.SEARCH + "/" + key;
+        final Response response = doGet(uri,
+                                        pluginName == null ? DEFAULT_EMPTY_QUERY : ImmutableMap.<String, String>of(JaxrsResource.QUERY_PAYMENT_METHOD_PLUGIN_NAME, pluginName),
+                                        DEFAULT_HTTP_TIMEOUT_SEC);
+        Assert.assertEquals(response.getStatusCode(), Status.OK.getStatusCode());
+
+        final String baseJson = response.getResponseBody();
+        final List<PaymentMethodJson> objFromJson = mapper.readValue(baseJson, new TypeReference<List<PaymentMethodJson>>() {});
+        Assert.assertNotNull(objFromJson);
+
+        return objFromJson;
+    }
+
     protected void deletePaymentMethod(final String paymentMethodId, final Boolean deleteDefault) throws IOException {
         final String paymentMethodURI = JaxrsResource.PAYMENT_METHODS_PATH + "/" + paymentMethodId;
 
@@ -838,6 +928,33 @@ public abstract class KillbillClient extends GuicyKillbillTestSuiteWithEmbeddedD
     }
 
     //
+    // CATALOG
+    //
+
+    public CatalogJsonSimple getSimpleCatalog() throws Exception {
+        final Response response = doGet(JaxrsResource.CATALOG_PATH + "/simpleCatalog", DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
+        Assert.assertEquals(response.getStatusCode(), Status.OK.getStatusCode());
+        final String body = response.getResponseBody();
+        return mapper.readValue(body, CatalogJsonSimple.class);
+    }
+
+    public List<PlanDetailJson> getAvailableAddons(final String baseProductName) throws Exception {
+        final Response response = doGet(JaxrsResource.CATALOG_PATH + "/availableAddons",
+                                        ImmutableMap.<String, String>of("baseProductName", baseProductName),
+                                        DEFAULT_HTTP_TIMEOUT_SEC);
+        Assert.assertEquals(response.getStatusCode(), Status.OK.getStatusCode());
+        final String body = response.getResponseBody();
+        return mapper.readValue(body, new TypeReference<List<PlanDetailJson>>() {});
+    }
+
+    public List<PlanDetailJson> getBasePlans() throws Exception {
+        final Response response = doGet(JaxrsResource.CATALOG_PATH + "/availableBasePlans", DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
+        Assert.assertEquals(response.getStatusCode(), Status.OK.getStatusCode());
+        final String body = response.getResponseBody();
+        return mapper.readValue(body, new TypeReference<List<PlanDetailJson>>() {});
+    }
+
+    //
     // HTTP CLIENT HELPERS
     //
     protected Response doPost(final String uri, @Nullable final String body, final Map<String, String> queryParams, final int timeoutSec) {
@@ -897,7 +1014,7 @@ public abstract class KillbillClient extends GuicyKillbillTestSuiteWithEmbeddedD
         return executeAndWait(builder, timeoutSec, false);
     }
 
-    private Response executeAndWait(final BoundRequestBuilder builder, final int timeoutSec, final boolean addContextHeader) {
+    protected Response executeAndWait(final BoundRequestBuilder builder, final int timeoutSec, final boolean addContextHeader) {
 
         if (addContextHeader) {
             builder.addHeader(JaxrsResource.HDR_CREATED_BY, createdBy);
@@ -905,6 +1022,16 @@ public abstract class KillbillClient extends GuicyKillbillTestSuiteWithEmbeddedD
             builder.addHeader(JaxrsResource.HDR_COMMENT, comment);
         }
 
+        if (username != null && password != null) {
+            final Realm realm = new Realm.RealmBuilder()
+                    .setPrincipal(username)
+                    .setPassword(password)
+                    .setUsePreemptiveAuth(true)
+                    .setScheme(AuthScheme.BASIC)
+                    .build();
+            builder.setRealm(realm);
+        }
+
         Response response = null;
         try {
             final ListenableFuture<Response> futureStatus =
@@ -926,7 +1053,7 @@ public abstract class KillbillClient extends GuicyKillbillTestSuiteWithEmbeddedD
         return String.format("http://%s:%d%s", config.getServerHost(), config.getServerPort(), uri);
     }
 
-    private BoundRequestBuilder getBuilderWithHeaderAndQuery(final String verb, final String url, final Map<String, String> queryParams) {
+    protected BoundRequestBuilder getBuilderWithHeaderAndQuery(final String verb, final String url, final Map<String, String> queryParams) {
         BoundRequestBuilder builder = null;
         if (verb.equals("GET")) {
             builder = httpClient.prepareGet(url);
@@ -945,6 +1072,8 @@ public abstract class KillbillClient extends GuicyKillbillTestSuiteWithEmbeddedD
         }
 
         builder.addHeader(HEADER_CONTENT_TYPE, CONTENT_TYPE);
+        builder.addHeader(HDR_API_KEY, apiKey);
+        builder.addHeader(HDR_API_SECRET, apiSecret);
         for (final Entry<String, String> q : queryParams.entrySet()) {
             builder.addQueryParameter(q.getKey(), q.getValue());
         }
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 4c90eab..239c4d3 100644
--- a/server/src/test/java/com/ning/billing/jaxrs/TestAccount.java
+++ b/server/src/test/java/com/ning/billing/jaxrs/TestAccount.java
@@ -23,6 +23,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.UUID;
 
+import javax.annotation.Nullable;
 import javax.ws.rs.core.Response.Status;
 
 import org.testng.Assert;
@@ -56,6 +57,9 @@ public class TestAccount extends TestJaxrsBase {
         final AccountJson retrievedAccount = getAccountByExternalKey(input.getExternalKey());
         Assert.assertTrue(retrievedAccount.equals(input));
 
+        // Try search endpoint
+        searchAccount(input, retrievedAccount);
+
         // Update Account
         final AccountJson newInput = new AccountJson(input.getAccountId(),
                                                      "zozo", 4, input.getExternalKey(), "rr@google.com", 18,
@@ -63,6 +67,9 @@ public class TestAccount extends TestJaxrsBase {
                                                      false, false);
         final AccountJson updatedAccount = updateAccount(input.getAccountId(), newInput);
         Assert.assertTrue(updatedAccount.equals(newInput));
+
+        // Try search endpoint
+        searchAccount(input, null);
     }
 
     @Test(groups = "slow")
@@ -250,7 +257,8 @@ public class TestAccount extends TestJaxrsBase {
 
     @Test(groups = "slow")
     public void testTags() throws Exception {
-        final String accountId = UUID.randomUUID().toString();
+        final AccountJson input = createAccount();
+        final String accountId = input.getAccountId();
         final String uri = JaxrsResource.ACCOUNTS_PATH + "/" + accountId + "/" + JaxrsResource.TAGS;
         final String accountTagsUrl = getUrlFromUri(uri);
         // Use tag definition for AUTO_PAY_OFF
@@ -280,7 +288,6 @@ public class TestAccount extends TestJaxrsBase {
 
     @Test(groups = "slow")
     public void testCustomFields() throws Exception {
-
         final AccountJson accountJson = createAccount("yoyoq", "gfgrqe", "yoyoq@yahoo.com");
         assertNotNull(accountJson);
 
@@ -299,4 +306,32 @@ public class TestAccount extends TestJaxrsBase {
         response = doGetWithUrl(url, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
         Assert.assertEquals(response.getStatusCode(), Status.OK.getStatusCode());
     }
+
+    private void searchAccount(final AccountJson input, @Nullable final AccountJson output) throws Exception {
+        // Search by name
+        doSearchAccount(input.getName(), output);
+
+        // Search by email
+        doSearchAccount(input.getEmail(), output);
+
+        // Search by company name
+        doSearchAccount(input.getCompany(), output);
+
+        // Search by external key.
+        // Note: we will always find a match since we don't update it
+        final List<AccountJson> accountsByExternalKey = searchAccountsByKey(input.getExternalKey());
+        Assert.assertEquals(accountsByExternalKey.size(), 1);
+        Assert.assertEquals(accountsByExternalKey.get(0).getAccountId(), input.getAccountId());
+        Assert.assertEquals(accountsByExternalKey.get(0).getExternalKey(), input.getExternalKey());
+    }
+
+    private void doSearchAccount(final String key, @Nullable final AccountJson output) throws Exception {
+        final List<AccountJson> accountsByKey = searchAccountsByKey(key);
+        if (output == null) {
+            Assert.assertEquals(accountsByKey.size(), 0);
+        } else {
+            Assert.assertEquals(accountsByKey.size(), 1);
+            Assert.assertEquals(accountsByKey.get(0), output);
+        }
+    }
 }
diff --git a/server/src/test/java/com/ning/billing/jaxrs/TestCatalog.java b/server/src/test/java/com/ning/billing/jaxrs/TestCatalog.java
index 3390b7d..8291fb9 100644
--- a/server/src/test/java/com/ning/billing/jaxrs/TestCatalog.java
+++ b/server/src/test/java/com/ning/billing/jaxrs/TestCatalog.java
@@ -13,29 +13,55 @@
  * License for the specific language governing permissions and limitations
  * under the License.
  */
+
 package com.ning.billing.jaxrs;
 
-import javax.ws.rs.core.Response.Status;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
 
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 import org.testng.Assert;
 import org.testng.annotations.Test;
 
 import com.ning.billing.jaxrs.json.CatalogJsonSimple;
-import com.ning.billing.jaxrs.resources.JaxrsResource;
-import com.ning.http.client.Response;
+import com.ning.billing.jaxrs.json.CatalogJsonSimple.PlanJson;
+import com.ning.billing.jaxrs.json.CatalogJsonSimple.ProductJson;
+import com.ning.billing.jaxrs.json.PlanDetailJson;
 
 public class TestCatalog extends TestJaxrsBase {
 
-    private static final Logger log = LoggerFactory.getLogger(TestAccount.class);
-
-    @Test(groups = "slow", enabled = true)
+    @Test(groups = "slow")
     public void testCatalogSimple() throws Exception {
-        Response response = doGet(JaxrsResource.CATALOG_PATH + "/simpleCatalog", DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
-        Assert.assertEquals(response.getStatusCode(), Status.OK.getStatusCode());
-        String body = response.getResponseBody();
-        CatalogJsonSimple objFromJson = mapper.readValue(body, CatalogJsonSimple.class);
-        log.info("Yeaahh...");
+        final Set<String> allBasePlans = new HashSet<String>();
+
+        final CatalogJsonSimple catalogJsonSimple = getSimpleCatalog();
+        for (final ProductJson productJson : catalogJsonSimple.getProducts()) {
+            if (!"BASE".equals(productJson.getType())) {
+                Assert.assertEquals(productJson.getIncluded().size(), 0);
+                Assert.assertEquals(productJson.getAvailable().size(), 0);
+                continue;
+            }
+
+            // Save all plans for later (see below)
+            for (final PlanJson planJson : productJson.getPlans()) {
+                allBasePlans.add(planJson.getName());
+            }
+
+            // Retrieve available products (addons) for that base product
+            final List<PlanDetailJson> availableAddons = getAvailableAddons(productJson.getName());
+            final Set<String> availableAddonsNames = new HashSet<String>();
+            for (final PlanDetailJson planDetailJson : availableAddons) {
+                availableAddonsNames.add(planDetailJson.getProductName());
+            }
+            Assert.assertEquals(availableAddonsNames, new HashSet<String>(productJson.getAvailable()));
+        }
+
+        // Verify base plans endpoint
+        final List<PlanDetailJson> basePlans = getBasePlans();
+        final Set<String> foundBasePlans = new HashSet<String>();
+        for (final PlanDetailJson planDetailJson : basePlans) {
+            foundBasePlans.add(planDetailJson.getPlanName());
+        }
+        Assert.assertEquals(foundBasePlans, allBasePlans);
     }
 }
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 97d8dbc..69833e4 100644
--- a/server/src/test/java/com/ning/billing/jaxrs/TestInvoice.java
+++ b/server/src/test/java/com/ning/billing/jaxrs/TestInvoice.java
@@ -52,6 +52,10 @@ public class TestInvoice extends TestJaxrsBase {
         final InvoiceJsonSimple firstInvoiceJson = getInvoice(invoiceJsonSimple.getInvoiceId());
         assertEquals(firstInvoiceJson, invoiceJsonSimple);
 
+        // Check we can retrieve the invoice by number
+        final InvoiceJsonSimple firstInvoiceByNumberJson = getInvoice(invoiceJsonSimple.getInvoiceNumber());
+        assertEquals(firstInvoiceByNumberJson, invoiceJsonSimple);
+
         // Then create a dryRun Invoice
         final DateTime futureDate = clock.getUTCNow().plusMonths(1).plusDays(3);
         createDryRunInvoice(accountJson.getAccountId(), futureDate);
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 31014eb..d900118 100644
--- a/server/src/test/java/com/ning/billing/jaxrs/TestJaxrsBase.java
+++ b/server/src/test/java/com/ning/billing/jaxrs/TestJaxrsBase.java
@@ -19,14 +19,15 @@ package com.ning.billing.jaxrs;
 import java.io.IOException;
 import java.net.URL;
 import java.util.EventListener;
-import java.util.HashMap;
 import java.util.Iterator;
 import java.util.Map;
 
 import javax.inject.Inject;
 import javax.servlet.Servlet;
+import javax.servlet.ServletContext;
 
-import com.ning.billing.entitlement.glue.DefaultEntitlementModule;
+import org.apache.shiro.web.env.EnvironmentLoaderListener;
+import org.apache.shiro.web.servlet.ShiroFilter;
 import org.eclipse.jetty.servlet.FilterHolder;
 import org.joda.time.LocalDate;
 import org.skife.config.ConfigSource;
@@ -37,6 +38,7 @@ import org.testng.annotations.BeforeClass;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.BeforeSuite;
 
+import com.ning.billing.DBTestingHelper;
 import com.ning.billing.GuicyKillbillTestWithEmbeddedDBModule;
 import com.ning.billing.KillbillConfigSource;
 import com.ning.billing.account.glue.DefaultAccountModule;
@@ -44,9 +46,8 @@ import com.ning.billing.api.TestApiListener;
 import com.ning.billing.beatrix.glue.BeatrixModule;
 import com.ning.billing.bus.api.PersistentBus;
 import com.ning.billing.catalog.glue.CatalogModule;
-import com.ning.billing.dbi.DBTestingHelper;
-import com.ning.billing.dbi.MysqlTestingHelper;
-import com.ning.billing.subscription.glue.DefaultSubscriptionModule;
+import com.ning.billing.commons.embeddeddb.EmbeddedDB;
+import com.ning.billing.entitlement.glue.DefaultEntitlementModule;
 import com.ning.billing.invoice.api.InvoiceNotifier;
 import com.ning.billing.invoice.glue.DefaultInvoiceModule;
 import com.ning.billing.invoice.notification.NullInvoiceNotifier;
@@ -57,7 +58,9 @@ import com.ning.billing.overdue.glue.DefaultOverdueModule;
 import com.ning.billing.payment.glue.PaymentModule;
 import com.ning.billing.payment.provider.MockPaymentProviderPluginModule;
 import com.ning.billing.server.listeners.KillbillGuiceListener;
+import com.ning.billing.server.modules.KillBillShiroWebModule;
 import com.ning.billing.server.modules.KillbillServerModule;
+import com.ning.billing.subscription.glue.DefaultSubscriptionModule;
 import com.ning.billing.tenant.glue.TenantModule;
 import com.ning.billing.usage.glue.UsageModule;
 import com.ning.billing.util.cache.CacheControllerDispatcher;
@@ -71,9 +74,12 @@ import com.ning.billing.util.glue.CacheModule;
 import com.ning.billing.util.glue.CallContextModule;
 import com.ning.billing.util.glue.CustomFieldModule;
 import com.ning.billing.util.glue.ExportModule;
+import com.ning.billing.util.glue.KillBillShiroAopModule;
+import com.ning.billing.util.glue.KillBillShiroModule;
 import com.ning.billing.util.glue.NonEntityDaoModule;
 import com.ning.billing.util.glue.NotificationQueueModule;
 import com.ning.billing.util.glue.RecordIdModule;
+import com.ning.billing.util.glue.SecurityModule;
 import com.ning.billing.util.glue.TagStoreModule;
 import com.ning.http.client.AsyncHttpClient;
 import com.ning.http.client.AsyncHttpClientConfig;
@@ -84,6 +90,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.SerializationFeature;
 import com.fasterxml.jackson.datatype.joda.JodaModule;
 import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
 import com.google.inject.Module;
 
 import static org.testng.Assert.assertNotNull;
@@ -123,17 +130,17 @@ public class TestJaxrsBase extends KillbillClient {
 
     public static class TestKillbillGuiceListener extends KillbillGuiceListener {
 
-        private final TestKillbillServerModule module;
+        private final EmbeddedDB helper;
 
 
-        public TestKillbillGuiceListener(final DBTestingHelper helper) {
+        public TestKillbillGuiceListener(final EmbeddedDB helper) {
             super();
-            this.module = new TestKillbillServerModule(helper);
+            this.helper = helper;
         }
 
         @Override
-        protected Module getModule() {
-            return module;
+        protected Module getModule(final ServletContext servletContext) {
+            return new TestKillbillServerModule(helper, servletContext);
         }
 
     }
@@ -152,10 +159,10 @@ public class TestJaxrsBase extends KillbillClient {
 
     public static class TestKillbillServerModule extends KillbillServerModule {
 
-        private final DBTestingHelper helper;
+        private final EmbeddedDB helper;
 
-        public TestKillbillServerModule(final DBTestingHelper helper) {
-            super();
+        public TestKillbillServerModule(final EmbeddedDB helper, final ServletContext servletContext) {
+            super(servletContext);
             this.helper = helper;
         }
 
@@ -198,7 +205,7 @@ public class TestJaxrsBase extends KillbillClient {
             install(new EmailModule(configSource));
             install(new CacheModule(configSource));
             install(new NonEntityDaoModule());
-            install(new TestGlobalLockerModule(helper));
+            install(new TestGlobalLockerModule(DBTestingHelper.get()));
             install(new CustomFieldModule());
             install(new TagStoreModule());
             install(new AuditModule());
@@ -221,6 +228,9 @@ public class TestJaxrsBase extends KillbillClient {
             install(new UsageModule(configSource));
             install(new RecordIdModule());
             installClock();
+            install(new KillBillShiroWebModule(servletContext));
+            install(new KillBillShiroAopModule());
+            install(new SecurityModule());
         }
     }
 
@@ -233,6 +243,11 @@ public class TestJaxrsBase extends KillbillClient {
         busHandler.reset();
         clock.resetDeltaFromReality();
         clock.setDay(new LocalDate(2012, 8, 25));
+
+        loginAsAdmin();
+
+        // Recreate the tenant (tables have been cleaned-up)
+        createTenant(DEFAULT_API_KEY, DEFAULT_API_SECRET);
     }
 
     @AfterMethod(groups = "slow")
@@ -245,17 +260,15 @@ public class TestJaxrsBase extends KillbillClient {
     public void beforeClass() throws Exception {
         loadConfig();
 
-
         listener.getInstantiatedInjector().injectMembers(this);
 
         httpClient = new AsyncHttpClient(new AsyncHttpClientConfig.Builder().setRequestTimeoutInMs(DEFAULT_HTTP_TIMEOUT_SEC * 1000).build());
+
         mapper = new ObjectMapper();
         mapper.registerModule(new JodaModule());
         mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
 
-        //mapper.setPropertyNamingStrategy(new PropertyNamingStrategy.LowerCaseWithUnderscoresStrategy());
-
-        busHandler = new TestApiListener(null, getDBTestingHelper().getDBI());
+        busHandler = new TestApiListener(null, dbi);
     }
 
     protected void loadConfig() {
@@ -264,9 +277,9 @@ public class TestJaxrsBase extends KillbillClient {
         }
 
         // For shiro (outside of Guice control)
-        System.setProperty("com.ning.jetty.jdbi.url", getDBTestingHelper().getJdbcConnectionString());
-        System.setProperty("com.ning.jetty.jdbi.user", MysqlTestingHelper.USERNAME);
-        System.setProperty("com.ning.jetty.jdbi.password", MysqlTestingHelper.PASSWORD);
+        System.setProperty("com.ning.jetty.jdbi.url", DBTestingHelper.get().getJdbcConnectionString());
+        System.setProperty("com.ning.jetty.jdbi.user", DBTestingHelper.get().getUsername());
+        System.setProperty("com.ning.jetty.jdbi.password", DBTestingHelper.get().getPassword());
     }
 
     @BeforeSuite(groups = "slow")
@@ -275,27 +288,26 @@ public class TestJaxrsBase extends KillbillClient {
         loadSystemPropertiesFromClasspath("/killbill.properties");
         loadConfig();
 
-        listener = new TestKillbillGuiceListener(getDBTestingHelper());
-        server = new HttpServer();
+        listener = new TestKillbillGuiceListener(helper);
 
+        server = new HttpServer();
         server.configure(config, getListeners(), getFilters());
-
         server.start();
-
-        listener.getInstantiatedInjector().injectMembers(this);
     }
 
     protected Iterable<EventListener> getListeners() {
         return new Iterable<EventListener>() {
             @Override
             public Iterator<EventListener> iterator() {
+                // Note! This needs to be in sync with web.xml
                 return ImmutableList.<EventListener>of(listener).iterator();
             }
         };
     }
 
     protected Map<FilterHolder, String> getFilters() {
-        return new HashMap<FilterHolder, String>();
+        // Note! This needs to be in sync with web.xml
+        return ImmutableMap.<FilterHolder, String>of(new FilterHolder(new ShiroFilter()), "/*");
     }
 
     @AfterSuite(groups = "slow")
diff --git a/server/src/test/java/com/ning/billing/jaxrs/TestPaymentMethod.java b/server/src/test/java/com/ning/billing/jaxrs/TestPaymentMethod.java
new file mode 100644
index 0000000..4d1e2f8
--- /dev/null
+++ b/server/src/test/java/com/ning/billing/jaxrs/TestPaymentMethod.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2010-2013 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;
+
+import java.util.List;
+import java.util.UUID;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.ning.billing.jaxrs.json.AccountJson;
+import com.ning.billing.jaxrs.json.PaymentMethodJson;
+
+public class TestPaymentMethod extends TestJaxrsBase {
+
+    @Test(groups = "slow")
+    public void testSearchPaymentMethods() throws Exception {
+        // Search random key
+        Assert.assertEquals(searchPaymentMethodsByKey(UUID.randomUUID().toString()).size(), 0);
+        Assert.assertEquals(searchPaymentMethodsByKeyAndPlugin(UUID.randomUUID().toString(), PLUGIN_NAME).size(), 0);
+
+        // Create a payment method
+        final AccountJson accountJson = createAccountWithDefaultPaymentMethod();
+        final PaymentMethodJson paymentMethodJson = getPaymentMethodWithPluginInfo(accountJson.getPaymentMethodId());
+
+        // Search random key again
+        Assert.assertEquals(searchPaymentMethodsByKey(UUID.randomUUID().toString()).size(), 0);
+        Assert.assertEquals(searchPaymentMethodsByKeyAndPlugin(UUID.randomUUID().toString(), PLUGIN_NAME).size(), 0);
+
+        // Make sure we can search the test plugin
+        // Values are hardcoded in TestPaymentMethodPluginBase and the search logic is in MockPaymentProviderPlugin
+        doSearch("Foo", paymentMethodJson);
+        // Last 4
+        doSearch("4365", paymentMethodJson);
+        // Name
+        doSearch("Bozo", paymentMethodJson);
+        // City
+        doSearch("SF", paymentMethodJson);
+        // State
+        doSearch("CA", paymentMethodJson);
+        // Country
+        doSearch("Zimbawe", paymentMethodJson);
+    }
+
+    private void doSearch(final String searchKey, final PaymentMethodJson paymentMethodJson) throws Exception {
+        final List<PaymentMethodJson> results1 = searchPaymentMethodsByKey(searchKey);
+        Assert.assertEquals(results1.size(), 1);
+        Assert.assertEquals(results1.get(0), paymentMethodJson);
+
+        final List<PaymentMethodJson> results2 = searchPaymentMethodsByKeyAndPlugin(searchKey, PLUGIN_NAME);
+        Assert.assertEquals(results2.size(), 1);
+        Assert.assertEquals(results2.get(0), paymentMethodJson);
+    }
+}
diff --git a/server/src/test/java/com/ning/billing/jaxrs/TestPushNotification.java b/server/src/test/java/com/ning/billing/jaxrs/TestPushNotification.java
index 83ab8cf..68d5a6d 100644
--- a/server/src/test/java/com/ning/billing/jaxrs/TestPushNotification.java
+++ b/server/src/test/java/com/ning/billing/jaxrs/TestPushNotification.java
@@ -68,7 +68,7 @@ public class TestPushNotification extends TestJaxrsBase {
 
     private boolean waitForCallbacksToComplete() throws InterruptedException {
 
-        long remainingMs = 5000;
+        long remainingMs = 20000;
         do {
             if (callbackCompleted) {
                 break;
diff --git a/server/src/test/java/com/ning/billing/jaxrs/TestSecurity.java b/server/src/test/java/com/ning/billing/jaxrs/TestSecurity.java
new file mode 100644
index 0000000..3c820d8
--- /dev/null
+++ b/server/src/test/java/com/ning/billing/jaxrs/TestSecurity.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2010-2013 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;
+
+import java.util.HashSet;
+import java.util.List;
+
+import javax.annotation.Nullable;
+import javax.ws.rs.core.Response.Status;
+
+import org.apache.shiro.web.servlet.ShiroHttpSession;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.ning.billing.jaxrs.resources.JaxrsResource;
+import com.ning.billing.security.Permission;
+import com.ning.http.client.AsyncHttpClient.BoundRequestBuilder;
+import com.ning.http.client.Cookie;
+import com.ning.http.client.Response;
+
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.google.common.base.Predicate;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+
+public class TestSecurity extends TestJaxrsBase {
+
+    @Test(groups = "slow")
+    public void testPermissions() throws Exception {
+        logout();
+
+        final Response anonResponse = doGet(JaxrsResource.SECURITY_PATH + "/permissions", DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
+        Assert.assertEquals(anonResponse.getStatusCode(), Status.UNAUTHORIZED.getStatusCode());
+
+        // See src/test/resources/shiro.ini
+
+        final List<String> pierresPermissions = getPermissions("pierre", "password");
+        Assert.assertEquals(pierresPermissions.size(), 2);
+        Assert.assertEquals(new HashSet<String>(pierresPermissions), ImmutableSet.<String>of(Permission.INVOICE_CAN_CREDIT.toString(), Permission.INVOICE_CAN_ITEM_ADJUST.toString()));
+
+        final List<String> stephanesPermissions = getPermissions("stephane", "password");
+        Assert.assertEquals(stephanesPermissions.size(), 1);
+        Assert.assertEquals(new HashSet<String>(stephanesPermissions), ImmutableSet.<String>of(Permission.PAYMENT_CAN_REFUND.toString()));
+    }
+
+    @Test(groups = "slow")
+    public void testSession() throws Exception {
+        loginAs("pierre", "password");
+
+        final Response firstResponse = doGet(JaxrsResource.SECURITY_PATH + "/permissions", DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
+        Assert.assertEquals(firstResponse.getStatusCode(), Status.OK.getStatusCode());
+        Assert.assertEquals(((List) mapper.readValue(firstResponse.getResponseBody(), new TypeReference<List<String>>() {})).size(), 2);
+
+        // Retrieve the session id
+        final Cookie session = Iterables.find(firstResponse.getCookies(),
+                                              new Predicate<Cookie>() {
+                                                  @Override
+                                                  public boolean apply(@Nullable final Cookie cookie) {
+                                                      return ShiroHttpSession.DEFAULT_SESSION_ID_NAME.equals(cookie.getName());
+                                                  }
+                                              });
+
+        // Make sure we don't use the credentials anymore
+        logout();
+
+        // Re-issue the query with the cookie
+        final String url = String.format("http://%s:%d%s", config.getServerHost(), config.getServerPort(), JaxrsResource.SECURITY_PATH + "/permissions");
+        final BoundRequestBuilder builder = getBuilderWithHeaderAndQuery("GET", url, DEFAULT_EMPTY_QUERY);
+        builder.addCookie(session);
+        final Response secondResponse = executeAndWait(builder, DEFAULT_HTTP_TIMEOUT_SEC, false);
+        Assert.assertEquals(secondResponse.getStatusCode(), Status.OK.getStatusCode());
+        Assert.assertEquals(((List) mapper.readValue(firstResponse.getResponseBody(), new TypeReference<List<String>>() {})).size(), 2);
+    }
+}
diff --git a/server/src/test/java/com/ning/billing/server/security/TestKillbillJdbcRealm.java b/server/src/test/java/com/ning/billing/server/security/TestKillbillJdbcRealm.java
index ac06a5a..b193de3 100644
--- a/server/src/test/java/com/ning/billing/server/security/TestKillbillJdbcRealm.java
+++ b/server/src/test/java/com/ning/billing/server/security/TestKillbillJdbcRealm.java
@@ -28,7 +28,6 @@ import org.testng.Assert;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 
-import com.ning.billing.dbi.MysqlTestingHelper;
 import com.ning.billing.jaxrs.TestJaxrsBase;
 import com.ning.billing.tenant.api.DefaultTenant;
 import com.ning.billing.tenant.dao.DefaultTenantDao;
@@ -50,16 +49,16 @@ public class TestKillbillJdbcRealm extends TestJaxrsBase {
         super.beforeMethod();
 
         // Create the tenant
-        final DefaultTenantDao tenantDao = new DefaultTenantDao(getDBI(), clock, cacheControllerDispatcher, new DefaultNonEntityDao(getDBI()));
+        final DefaultTenantDao tenantDao = new DefaultTenantDao(dbi, clock, cacheControllerDispatcher, new DefaultNonEntityDao(dbi));
         tenant = new DefaultTenant(UUID.randomUUID(), null, null, UUID.randomUUID().toString(),
                                    UUID.randomUUID().toString(), UUID.randomUUID().toString());
         tenantDao.create(new TenantModelDao(tenant), internalCallContext);
 
         // Setup the security manager
         final BoneCPConfig dbConfig = new BoneCPConfig();
-        dbConfig.setJdbcUrl(getDBTestingHelper().getJdbcConnectionString());
-        dbConfig.setUsername(MysqlTestingHelper.USERNAME);
-        dbConfig.setPassword(MysqlTestingHelper.PASSWORD);
+        dbConfig.setJdbcUrl(helper.getJdbcConnectionString());
+        dbConfig.setUsername(helper.getUsername());
+        dbConfig.setPassword(helper.getPassword());
 
         final KillbillJdbcRealm jdbcRealm;
         jdbcRealm = new KillbillJdbcRealm();
diff --git a/server/src/test/java/com/ning/billing/server/security/TestTenantFilter.java b/server/src/test/java/com/ning/billing/server/security/TestTenantFilter.java
index d4a0dbf..ef60130 100644
--- a/server/src/test/java/com/ning/billing/server/security/TestTenantFilter.java
+++ b/server/src/test/java/com/ning/billing/server/security/TestTenantFilter.java
@@ -16,56 +16,30 @@
 
 package com.ning.billing.server.security;
 
-import java.util.EventListener;
-import java.util.Iterator;
-import java.util.Map;
-
 import javax.ws.rs.core.Response.Status;
 
-import org.apache.shiro.web.env.EnvironmentLoaderListener;
-import org.apache.shiro.web.servlet.ShiroFilter;
-import org.eclipse.jetty.servlet.FilterHolder;
 import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 
 import com.ning.billing.jaxrs.TestJaxrsBase;
 import com.ning.billing.jaxrs.json.AccountJson;
 import com.ning.billing.server.listeners.KillbillGuiceListener;
-import com.ning.http.client.AsyncHttpClient;
-import com.ning.http.client.AsyncHttpClientConfig;
-import com.ning.http.client.Realm;
-import com.ning.http.client.Realm.AuthScheme;
-
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
 
-public class TestTenantFilter extends TestJaxrsBase  {
-
-    @Override
-    protected void loadConfig() {
-        System.setProperty(KillbillGuiceListener.KILLBILL_MULTITENANT_PROPERTY, "true");
-        super.loadConfig();
-    }
+// Pure Multi-Tenancy test (no RBAC)
+public class TestTenantFilter extends TestJaxrsBase {
 
-    @Override
-    protected Iterable<EventListener> getListeners() {
-        return new Iterable<EventListener>() {
-            @Override
-            public Iterator<EventListener> iterator() {
-                return ImmutableList.<EventListener>of(listener, new EnvironmentLoaderListener()).iterator();
-            }
-        };
+    @AfterMethod(groups = "slow")
+    public void tearDown() throws Exception {
+        // Default credentials
+        loginTenant(DEFAULT_API_KEY, DEFAULT_API_SECRET);
     }
 
-    @Override
-    protected Map<FilterHolder, String> getFilters() {
-        return ImmutableMap.<FilterHolder, String>of(new FilterHolder(ShiroFilter.class), "/*");
-    }
-
-    // TODO Need to run by itself for now as the server from the test suite doesn't have the Shiro setup
-    @Test(groups = "slow", enabled = false)
+    @Test(groups = "slow")
     public void testTenantShouldOnlySeeOwnAccount() throws Exception {
         // Try to create an account without being logged-in
+        logoutTenant();
         Assert.assertEquals(createAccountNoValidation().getStatusCode(), Status.UNAUTHORIZED.getStatusCode());
 
         // Create the tenant
@@ -105,18 +79,12 @@ public class TestTenantFilter extends TestJaxrsBase  {
     }
 
     private void loginTenant(final String apiKey, final String apiSecret) {
-        final AsyncHttpClientConfig.Builder builder = new AsyncHttpClientConfig.Builder();
-        final Realm realm = new Realm.RealmBuilder()
-                .setPrincipal(apiKey)
-                .setPassword(apiSecret)
-                .setUsePreemptiveAuth(true)
-                .setScheme(AuthScheme.BASIC)
-                .build();
-        builder.setRealm(realm).setRequestTimeoutInMs(DEFAULT_HTTP_TIMEOUT_SEC * 1000).build();
-        httpClient = new AsyncHttpClient(builder.build());
+        this.apiKey = apiKey;
+        this.apiSecret = apiSecret;
     }
 
     private void logoutTenant() {
-        httpClient = new AsyncHttpClient(new AsyncHttpClientConfig.Builder().setRequestTimeoutInMs(DEFAULT_HTTP_TIMEOUT_SEC * 1000).build());
+        apiKey = "";
+        apiSecret = "";
     }
 }
diff --git a/server/src/test/resources/killbill.properties b/server/src/test/resources/killbill.properties
index 6a30a5c..dd7b4f2 100644
--- a/server/src/test/resources/killbill.properties
+++ b/server/src/test/resources/killbill.properties
@@ -37,5 +37,8 @@ killbill.billing.persistent.bus.claimed=1
 
 killbill.osgi.bundle.install.dir=/var/tmp/somethingthatdoesnotexist
 
+# Speed up from the (more secure) default
+killbill.server.multitenant.hash_iterations=10
+
 ANTLR_USE_DIRECT_CLASS_LOADING=true
 
diff --git a/server/src/test/resources/shiro.ini b/server/src/test/resources/shiro.ini
index 664ee13..4f9db89 100644
--- a/server/src/test/resources/shiro.ini
+++ b/server/src/test/resources/shiro.ini
@@ -1,6 +1,6 @@
 ###################################################################################
 #                                                                                 #
-#                   Copyright 2010-2012 Ning, Inc.                                #
+#                   Copyright 2010-2013 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   #
@@ -16,22 +16,15 @@
 #                                                                                 #
 ###################################################################################
 
-[main]
-# Bypass the servlet container completely for session management and delegate
-# it to Shiro (to be portable across servlet containers)
-# The default session timeout is 30 minutes.
-sessionManager = org.apache.shiro.web.session.mgt.DefaultWebSessionManager
-# Use the configured native session manager
-securityManager.sessionManager = $sessionManager
+[users]
+tester = tester, admin
+pierre = password, creditor
+stephane = password, refunder
 
-jdbcRealm=com.ning.billing.server.security.KillbillJdbcRealm
+[roles]
+admin = *:*
+creditor = invoice:credit, invoice:item_adjust
+refunder = payment:refund
 
 [urls]
-# Special endpoints: healthcheck, tenant API.
-# TODO: don't secure them for now - eventually require admin privileges
-/1.0/healthcheck = anon
-/1.0/kb/tenants/** = anon
-# For all other resources, require basic auth
-# TODO: ssl, authcBasic
-# Commented out because that seems to break the server tests that don't require authentification
-#/1.0/kb/** = authcBasic
+/1.0/kb/** = authcBasic
diff --git a/subscription/killbill-subscription.iml b/subscription/killbill-subscription.iml
index 3208953..9f2164a 100644
--- a/subscription/killbill-subscription.iml
+++ b/subscription/killbill-subscription.iml
@@ -12,6 +12,20 @@
     </content>
     <orderEntry type="inheritedJdk" />
     <orderEntry type="sourceFolder" forTests="false" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-catalog:test-jar:tests:0.3.6-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-payment:0.3.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-clock:0.1.7" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-queue:0.1.7" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-jdbi:0.1.7" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-notification:0.3.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-util:test-jar:tests:0.3.6-SNAPSHOT" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing.commons:killbill-clock:test-jar:tests:0.1.7" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing.commons:killbill-queue:test-jar:tests:0.1.7" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing:killbill-api:0.6.0-SNAPSHOT" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-catalog:test-jar:tests:0.5.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-payment:0.4.0-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-notification:0.4.0-SNAPSHOT" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-util:test-jar:tests:0.5.1-SNAPSHOT" level="project" />
     <orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-annotations:2.1.0" level="project" />
     <orderEntry type="library" scope="PROVIDED" name="Maven: com.google.code.findbugs:jsr305:1.3.9" level="project" />
     <orderEntry type="library" scope="PROVIDED" name="Maven: com.google.guava:guava:14.0.1" level="project" />
@@ -24,12 +38,12 @@
     <orderEntry type="library" scope="TEST" name="Maven: org.hamcrest:hamcrest-core:1.1" level="project" />
     <orderEntry type="library" scope="TEST" name="Maven: cglib:cglib-nodep:2.2" level="project" />
     <orderEntry type="library" scope="TEST" name="Maven: org.objenesis:objenesis:1.2" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing:killbill-api:0.3.3-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing:killbill-api:0.6.0-SNAPSHOT" level="project" />
     <orderEntry type="library" name="Maven: joda-time:joda-time:2.0" level="project" />
     <orderEntry type="module" module-name="killbill-catalog" scope="TEST" production-on-test="" />
-    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-catalog:test-jar:tests:0.3.6-SNAPSHOT" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-catalog:test-jar:tests:0.5.1-SNAPSHOT" level="project" />
     <orderEntry type="module" module-name="killbill-internal-api" />
-    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-payment:0.3.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-payment:0.4.0-SNAPSHOT" level="project" />
     <orderEntry type="library" name="Maven: org.skife.config:config-magic:0.14" level="project" />
     <orderEntry type="library" name="Maven: org.slf4j:slf4j-api:1.7.5" level="project" />
     <orderEntry type="module" module-name="killbill-util" />
@@ -40,13 +54,14 @@
     <orderEntry type="library" name="Maven: com.jolbox:bonecp:0.7.1.RELEASE" level="project" />
     <orderEntry type="library" name="Maven: com.mchange:c3p0:0.9.2" level="project" />
     <orderEntry type="library" name="Maven: com.mchange:mchange-commons-java:0.2.3.3" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-clock:0.1.7" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-queue:0.1.7" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-jdbi:0.1.7" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-clock:0.2.1" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-locker:0.2.1" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-queue:0.2.1" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-jdbi:0.2.1" level="project" />
     <orderEntry type="library" name="Maven: org.jdbi:jdbi:2.39.1" level="project" />
     <orderEntry type="library" name="Maven: com.yammer.metrics:metrics-core:2.1.2" level="project" />
     <orderEntry type="library" name="Maven: org.weakref:jmxutils:1.12" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-notification:0.3.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-notification:0.4.0-SNAPSHOT" level="project" />
     <orderEntry type="library" name="Maven: com.samskivert:jmustache:1.5" level="project" />
     <orderEntry type="library" name="Maven: net.sf.ehcache:ehcache-core:2.6.2" level="project" />
     <orderEntry type="library" scope="RUNTIME" name="Maven: org.antlr:stringtemplate:3.2.1" level="project" />
@@ -54,11 +69,18 @@
     <orderEntry type="library" name="Maven: org.apache.commons:commons-email:1.2" level="project" />
     <orderEntry type="library" name="Maven: javax.mail:mail:1.4.1" level="project" />
     <orderEntry type="library" name="Maven: javax.activation:activation:1.1" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.shiro:shiro-core:1.2.2" level="project" />
+    <orderEntry type="library" name="Maven: commons-beanutils:commons-beanutils:1.8.3" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.shiro:shiro-ehcache:1.2.2" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.shiro:shiro-guice:1.2.2" level="project" />
+    <orderEntry type="library" scope="PROVIDED" name="Maven: com.google.inject.extensions:guice-multibindings:3.0" level="project" />
+    <orderEntry type="library" name="Maven: org.slf4j:jcl-over-slf4j:1.7.5" level="project" />
     <orderEntry type="module" module-name="killbill-catalog" scope="TEST" />
     <orderEntry type="module" module-name="killbill-util" scope="TEST" production-on-test="" />
-    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-util:test-jar:tests:0.3.6-SNAPSHOT" level="project" />
-    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing.commons:killbill-clock:test-jar:tests:0.1.7" level="project" />
-    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing.commons:killbill-queue:test-jar:tests:0.1.7" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-util:test-jar:tests:0.5.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing.commons:killbill-clock:test-jar:tests:0.2.1" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing.commons:killbill-embeddeddb:0.2.1" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing.commons:killbill-queue:test-jar:tests:0.2.1" level="project" />
     <orderEntry type="library" scope="TEST" name="Maven: mysql:mysql-connector-mxj:5.0.12" level="project" />
     <orderEntry type="library" scope="TEST" name="Maven: mysql:mysql-connector-mxj-db-files:5.0.12" level="project" />
     <orderEntry type="library" scope="RUNTIME" name="Maven: mysql:mysql-connector-java:5.1.22" level="project" />
diff --git a/subscription/pom.xml b/subscription/pom.xml
index 8ee1437..095314e 100644
--- a/subscription/pom.xml
+++ b/subscription/pom.xml
@@ -19,7 +19,7 @@
     <parent>
         <artifactId>killbill</artifactId>
         <groupId>com.ning.billing</groupId>
-        <version>0.3.6-SNAPSHOT</version>
+        <version>0.5.1-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <artifactId>killbill-subscription</artifactId>
@@ -95,6 +95,11 @@
         </dependency>
         <dependency>
             <groupId>com.ning.billing.commons</groupId>
+            <artifactId>killbill-embeddeddb</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.ning.billing.commons</groupId>
             <artifactId>killbill-queue</artifactId>
         </dependency>
         <dependency>
diff --git a/tenant/killbill-tenant.iml b/tenant/killbill-tenant.iml
index 342033b..cf88d12 100644
--- a/tenant/killbill-tenant.iml
+++ b/tenant/killbill-tenant.iml
@@ -11,17 +11,25 @@
     </content>
     <orderEntry type="inheritedJdk" />
     <orderEntry type="sourceFolder" forTests="false" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-payment:0.3.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-clock:0.1.7" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-queue:0.1.7" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-jdbi:0.1.7" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-notification:0.3.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-util:test-jar:tests:0.3.6-SNAPSHOT" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing.commons:killbill-clock:test-jar:tests:0.1.7" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.shiro:shiro-core:1.2.1" level="project" />
     <orderEntry type="library" scope="PROVIDED" name="Maven: com.google.code.findbugs:jsr305:1.3.9" level="project" />
     <orderEntry type="library" scope="PROVIDED" name="Maven: com.google.guava:guava:14.0.1" level="project" />
     <orderEntry type="library" scope="PROVIDED" name="Maven: com.google.inject:guice:3.0" level="project" />
     <orderEntry type="library" scope="PROVIDED" name="Maven: javax.inject:javax.inject:1" level="project" />
     <orderEntry type="library" scope="PROVIDED" name="Maven: aopalliance:aopalliance:1.0" level="project" />
     <orderEntry type="library" scope="TEST" name="Maven: com.h2database:h2:1.3.158" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing:killbill-api:0.3.3-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing:killbill-api:0.6.0-SNAPSHOT" level="project" />
     <orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-annotations:2.1.0" level="project" />
     <orderEntry type="library" name="Maven: joda-time:joda-time:2.0" level="project" />
     <orderEntry type="module" module-name="killbill-internal-api" />
-    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-payment:0.3.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-payment:0.4.0-SNAPSHOT" level="project" />
     <orderEntry type="library" name="Maven: org.skife.config:config-magic:0.14" level="project" />
     <orderEntry type="library" name="Maven: org.slf4j:slf4j-api:1.7.5" level="project" />
     <orderEntry type="module" module-name="killbill-util" />
@@ -32,13 +40,14 @@
     <orderEntry type="library" name="Maven: com.jolbox:bonecp:0.7.1.RELEASE" level="project" />
     <orderEntry type="library" name="Maven: com.mchange:c3p0:0.9.2" level="project" />
     <orderEntry type="library" name="Maven: com.mchange:mchange-commons-java:0.2.3.3" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-clock:0.1.7" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-queue:0.1.7" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-jdbi:0.1.7" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-clock:0.2.1" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-locker:0.2.1" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-queue:0.2.1" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-jdbi:0.2.1" level="project" />
     <orderEntry type="library" name="Maven: org.jdbi:jdbi:2.39.1" level="project" />
     <orderEntry type="library" name="Maven: com.yammer.metrics:metrics-core:2.1.2" level="project" />
     <orderEntry type="library" name="Maven: org.weakref:jmxutils:1.12" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-notification:0.3.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-notification:0.4.0-SNAPSHOT" level="project" />
     <orderEntry type="library" name="Maven: com.samskivert:jmustache:1.5" level="project" />
     <orderEntry type="library" name="Maven: net.sf.ehcache:ehcache-core:2.6.2" level="project" />
     <orderEntry type="library" scope="RUNTIME" name="Maven: org.antlr:stringtemplate:3.2.1" level="project" />
@@ -46,14 +55,19 @@
     <orderEntry type="library" name="Maven: org.apache.commons:commons-email:1.2" level="project" />
     <orderEntry type="library" name="Maven: javax.mail:mail:1.4.1" level="project" />
     <orderEntry type="library" name="Maven: javax.activation:activation:1.1" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.shiro:shiro-core:1.2.2" level="project" />
+    <orderEntry type="library" name="Maven: commons-beanutils:commons-beanutils:1.8.3" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.shiro:shiro-ehcache:1.2.2" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.shiro:shiro-guice:1.2.2" level="project" />
+    <orderEntry type="library" scope="PROVIDED" name="Maven: com.google.inject.extensions:guice-multibindings:3.0" level="project" />
+    <orderEntry type="library" name="Maven: org.slf4j:jcl-over-slf4j:1.7.5" level="project" />
     <orderEntry type="module" module-name="killbill-util" scope="TEST" production-on-test="" />
-    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-util:test-jar:tests:0.3.6-SNAPSHOT" level="project" />
-    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing.commons:killbill-clock:test-jar:tests:0.1.7" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-util:test-jar:tests:0.5.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing.commons:killbill-clock:test-jar:tests:0.2.1" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing.commons:killbill-embeddeddb:0.2.1" level="project" />
     <orderEntry type="library" scope="TEST" name="Maven: mysql:mysql-connector-mxj:5.0.12" level="project" />
     <orderEntry type="library" scope="TEST" name="Maven: mysql:mysql-connector-mxj-db-files:5.0.12" level="project" />
     <orderEntry type="library" scope="RUNTIME" name="Maven: mysql:mysql-connector-java:5.1.22" level="project" />
-    <orderEntry type="library" name="Maven: org.apache.shiro:shiro-core:1.2.1" level="project" />
-    <orderEntry type="library" name="Maven: commons-beanutils:commons-beanutils:1.8.3" level="project" />
     <orderEntry type="library" scope="TEST" name="Maven: org.mockito:mockito-all:1.9.0" level="project" />
     <orderEntry type="library" scope="TEST" name="Maven: org.slf4j:slf4j-simple:1.7.5" level="project" />
     <orderEntry type="library" scope="TEST" name="Maven: org.testng:testng:6.3.1" level="project" />

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

diff --git a/tenant/pom.xml b/tenant/pom.xml
index 66ebda4..63df7ee 100644
--- a/tenant/pom.xml
+++ b/tenant/pom.xml
@@ -19,7 +19,7 @@
     <parent>
         <artifactId>killbill</artifactId>
         <groupId>com.ning.billing</groupId>
-        <version>0.3.6-SNAPSHOT</version>
+        <version>0.5.1-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <artifactId>killbill-tenant</artifactId>
@@ -74,6 +74,11 @@
             <scope>test</scope>
         </dependency>
         <dependency>
+            <groupId>com.ning.billing.commons</groupId>
+            <artifactId>killbill-embeddeddb</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
             <groupId>joda-time</groupId>
             <artifactId>joda-time</artifactId>
         </dependency>
diff --git a/tenant/src/main/java/com/ning/billing/tenant/security/KillbillCredentialsMatcher.java b/tenant/src/main/java/com/ning/billing/tenant/security/KillbillCredentialsMatcher.java
index 31eb22d..f95478b 100644
--- a/tenant/src/main/java/com/ning/billing/tenant/security/KillbillCredentialsMatcher.java
+++ b/tenant/src/main/java/com/ning/billing/tenant/security/KillbillCredentialsMatcher.java
@@ -22,9 +22,11 @@ import org.apache.shiro.crypto.hash.Sha512Hash;
 
 public class KillbillCredentialsMatcher {
 
+    public static final String KILLBILL_TENANT_HASH_ITERATIONS_PROPERTY = "killbill.server.multitenant.hash_iterations";
+
     // See http://www.stormpath.com/blog/strong-password-hashing-apache-shiro and https://issues.apache.org/jira/browse/SHIRO-290
     public static final String HASH_ALGORITHM_NAME = Sha512Hash.ALGORITHM_NAME;
-    public static final int HASH_ITERATIONS = 500000;
+    public static final Integer HASH_ITERATIONS = Integer.parseInt(System.getProperty(KILLBILL_TENANT_HASH_ITERATIONS_PROPERTY, "200000"));
 
     private KillbillCredentialsMatcher() {}
 
diff --git a/usage/killbill-usage.iml b/usage/killbill-usage.iml
index 866d349..2b730d2 100644
--- a/usage/killbill-usage.iml
+++ b/usage/killbill-usage.iml
@@ -11,16 +11,27 @@
     </content>
     <orderEntry type="inheritedJdk" />
     <orderEntry type="sourceFolder" forTests="false" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-payment:0.3.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-clock:0.1.7" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-queue:0.1.7" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-jdbi:0.1.7" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-notification:0.3.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-util:test-jar:tests:0.3.6-SNAPSHOT" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing.commons:killbill-clock:test-jar:tests:0.1.7" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing:killbill-api:0.6.0-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-payment:0.4.0-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-notification:0.4.0-SNAPSHOT" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-util:test-jar:tests:0.5.1-SNAPSHOT" level="project" />
     <orderEntry type="library" scope="PROVIDED" name="Maven: com.google.guava:guava:14.0.1" level="project" />
     <orderEntry type="library" scope="PROVIDED" name="Maven: com.google.inject:guice:3.0" level="project" />
     <orderEntry type="library" scope="PROVIDED" name="Maven: javax.inject:javax.inject:1" level="project" />
     <orderEntry type="library" scope="PROVIDED" name="Maven: aopalliance:aopalliance:1.0" level="project" />
     <orderEntry type="library" scope="TEST" name="Maven: com.h2database:h2:1.3.158" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing:killbill-api:0.3.3-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing:killbill-api:0.6.0-SNAPSHOT" level="project" />
     <orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-annotations:2.1.0" level="project" />
     <orderEntry type="library" name="Maven: joda-time:joda-time:2.0" level="project" />
     <orderEntry type="module" module-name="killbill-internal-api" />
-    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-payment:0.3.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-payment:0.4.0-SNAPSHOT" level="project" />
     <orderEntry type="library" name="Maven: org.skife.config:config-magic:0.14" level="project" />
     <orderEntry type="library" name="Maven: org.slf4j:slf4j-api:1.7.5" level="project" />
     <orderEntry type="module" module-name="killbill-util" />
@@ -31,13 +42,14 @@
     <orderEntry type="library" name="Maven: com.jolbox:bonecp:0.7.1.RELEASE" level="project" />
     <orderEntry type="library" name="Maven: com.mchange:c3p0:0.9.2" level="project" />
     <orderEntry type="library" name="Maven: com.mchange:mchange-commons-java:0.2.3.3" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-clock:0.1.7" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-queue:0.1.7" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-jdbi:0.1.7" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-clock:0.2.1" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-locker:0.2.1" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-queue:0.2.1" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-jdbi:0.2.1" level="project" />
     <orderEntry type="library" name="Maven: org.jdbi:jdbi:2.39.1" level="project" />
     <orderEntry type="library" name="Maven: com.yammer.metrics:metrics-core:2.1.2" level="project" />
     <orderEntry type="library" name="Maven: org.weakref:jmxutils:1.12" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-notification:0.3.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-notification:0.4.0-SNAPSHOT" level="project" />
     <orderEntry type="library" name="Maven: com.samskivert:jmustache:1.5" level="project" />
     <orderEntry type="library" name="Maven: net.sf.ehcache:ehcache-core:2.6.2" level="project" />
     <orderEntry type="library" scope="RUNTIME" name="Maven: org.antlr:stringtemplate:3.2.1" level="project" />
@@ -45,9 +57,16 @@
     <orderEntry type="library" name="Maven: org.apache.commons:commons-email:1.2" level="project" />
     <orderEntry type="library" name="Maven: javax.mail:mail:1.4.1" level="project" />
     <orderEntry type="library" name="Maven: javax.activation:activation:1.1" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.shiro:shiro-core:1.2.2" level="project" />
+    <orderEntry type="library" name="Maven: commons-beanutils:commons-beanutils:1.8.3" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.shiro:shiro-ehcache:1.2.2" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.shiro:shiro-guice:1.2.2" level="project" />
+    <orderEntry type="library" scope="PROVIDED" name="Maven: com.google.inject.extensions:guice-multibindings:3.0" level="project" />
+    <orderEntry type="library" name="Maven: org.slf4j:jcl-over-slf4j:1.7.5" level="project" />
     <orderEntry type="module" module-name="killbill-util" scope="TEST" production-on-test="" />
-    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-util:test-jar:tests:0.3.6-SNAPSHOT" level="project" />
-    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing.commons:killbill-clock:test-jar:tests:0.1.7" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-util:test-jar:tests:0.5.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing.commons:killbill-clock:test-jar:tests:0.2.1" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing.commons:killbill-embeddeddb:0.2.1" level="project" />
     <orderEntry type="library" scope="TEST" name="Maven: mysql:mysql-connector-mxj:5.0.12" level="project" />
     <orderEntry type="library" scope="TEST" name="Maven: mysql:mysql-connector-mxj-db-files:5.0.12" level="project" />
     <orderEntry type="library" scope="RUNTIME" name="Maven: mysql:mysql-connector-java:5.1.22" level="project" />

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

diff --git a/usage/pom.xml b/usage/pom.xml
index 86b1e69..3010a2e 100644
--- a/usage/pom.xml
+++ b/usage/pom.xml
@@ -19,7 +19,7 @@
     <parent>
         <artifactId>killbill</artifactId>
         <groupId>com.ning.billing</groupId>
-        <version>0.3.6-SNAPSHOT</version>
+        <version>0.5.1-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <artifactId>killbill-usage</artifactId>
@@ -69,6 +69,11 @@
             <scope>test</scope>
         </dependency>
         <dependency>
+            <groupId>com.ning.billing.commons</groupId>
+            <artifactId>killbill-embeddeddb</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
             <groupId>joda-time</groupId>
             <artifactId>joda-time</artifactId>
         </dependency>
diff --git a/util/killbill-util.iml b/util/killbill-util.iml
index 1d9ecaf..0782507 100644
--- a/util/killbill-util.iml
+++ b/util/killbill-util.iml
@@ -12,6 +12,16 @@
     </content>
     <orderEntry type="inheritedJdk" />
     <orderEntry type="sourceFolder" forTests="false" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-payment:0.3.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-clock:0.1.7" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing.commons:killbill-clock:test-jar:tests:0.1.7" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-queue:0.1.7" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-jdbi:0.1.7" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing.commons:killbill-queue:test-jar:tests:0.1.7" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-notification:0.3.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing:killbill-api:0.6.0-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-payment:0.4.0-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-notification:0.4.0-SNAPSHOT" level="project" />
     <orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-annotations:2.1.0" level="project" />
     <orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-databind:2.1.0" level="project" />
     <orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-core:2.1.0" level="project" />
@@ -34,19 +44,21 @@
     <orderEntry type="library" name="Maven: org.slf4j:slf4j-api:1.7.5" level="project" />
     <orderEntry type="library" name="Maven: com.mchange:c3p0:0.9.2" level="project" />
     <orderEntry type="library" name="Maven: com.mchange:mchange-commons-java:0.2.3.3" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing:killbill-api:0.3.3-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing:killbill-api:0.6.0-SNAPSHOT" level="project" />
     <orderEntry type="module" module-name="killbill-internal-api" />
-    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-payment:0.3.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-payment:0.4.0-SNAPSHOT" level="project" />
     <orderEntry type="library" name="Maven: org.skife.config:config-magic:0.14" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-clock:0.1.7" level="project" />
-    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing.commons:killbill-clock:test-jar:tests:0.1.7" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-queue:0.1.7" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-jdbi:0.1.7" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-clock:0.2.1" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing.commons:killbill-clock:test-jar:tests:0.2.1" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing.commons:killbill-embeddeddb:0.2.1" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-locker:0.2.1" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-queue:0.2.1" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-jdbi:0.2.1" level="project" />
     <orderEntry type="library" name="Maven: org.jdbi:jdbi:2.39.1" level="project" />
     <orderEntry type="library" name="Maven: com.yammer.metrics:metrics-core:2.1.2" level="project" />
     <orderEntry type="library" name="Maven: org.weakref:jmxutils:1.12" level="project" />
-    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing.commons:killbill-queue:test-jar:tests:0.1.7" level="project" />
-    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-notification:0.3.1-SNAPSHOT" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing.commons:killbill-queue:test-jar:tests:0.2.1" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.plugin:killbill-plugin-api-notification:0.4.0-SNAPSHOT" level="project" />
     <orderEntry type="library" name="Maven: com.samskivert:jmustache:1.5" level="project" />
     <orderEntry type="library" scope="TEST" name="Maven: mysql:mysql-connector-java:5.1.22" level="project" />
     <orderEntry type="library" scope="TEST" name="Maven: mysql:mysql-connector-mxj:5.0.12" level="project" />
@@ -57,7 +69,12 @@
     <orderEntry type="library" name="Maven: org.apache.commons:commons-email:1.2" level="project" />
     <orderEntry type="library" name="Maven: javax.mail:mail:1.4.1" level="project" />
     <orderEntry type="library" name="Maven: javax.activation:activation:1.1" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.shiro:shiro-core:1.2.2" level="project" />
+    <orderEntry type="library" name="Maven: commons-beanutils:commons-beanutils:1.8.3" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.shiro:shiro-ehcache:1.2.2" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.shiro:shiro-guice:1.2.2" level="project" />
     <orderEntry type="library" scope="TEST" name="Maven: org.mockito:mockito-all:1.9.0" level="project" />
+    <orderEntry type="library" name="Maven: org.slf4j:jcl-over-slf4j:1.7.5" level="project" />
     <orderEntry type="library" scope="TEST" name="Maven: org.slf4j:slf4j-simple:1.7.5" level="project" />
     <orderEntry type="library" scope="TEST" name="Maven: org.testng:testng:6.3.1" level="project" />
     <orderEntry type="library" scope="TEST" name="Maven: junit:junit:3.8.1" level="project" />

util/pom.xml 29(+27 -2)

diff --git a/util/pom.xml b/util/pom.xml
index 2ca1b28..77e3017 100644
--- a/util/pom.xml
+++ b/util/pom.xml
@@ -12,7 +12,7 @@
     <parent>
         <artifactId>killbill</artifactId>
         <groupId>com.ning.billing</groupId>
-        <version>0.3.6-SNAPSHOT</version>
+        <version>0.5.1-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <artifactId>killbill-util</artifactId>
@@ -89,12 +89,20 @@
         </dependency>
         <dependency>
             <groupId>com.ning.billing.commons</groupId>
+            <artifactId>killbill-embeddeddb</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.ning.billing.commons</groupId>
+            <artifactId>killbill-locker</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.ning.billing.commons</groupId>
             <artifactId>killbill-queue</artifactId>
         </dependency>
         <dependency>
             <groupId>com.ning.billing.commons</groupId>
             <artifactId>killbill-queue</artifactId>
-            <version>${killbill-commons.version}</version>
             <type>test-jar</type>
             <scope>test</scope>
         </dependency>
@@ -152,6 +160,18 @@
             <artifactId>commons-email</artifactId>
         </dependency>
         <dependency>
+            <groupId>org.apache.shiro</groupId>
+            <artifactId>shiro-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.shiro</groupId>
+            <artifactId>shiro-ehcache</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.shiro</groupId>
+            <artifactId>shiro-guice</artifactId>
+        </dependency>
+        <dependency>
             <groupId>org.jdbi</groupId>
             <artifactId>jdbi</artifactId>
         </dependency>
@@ -165,6 +185,11 @@
             <artifactId>config-magic</artifactId>
         </dependency>
         <dependency>
+            <!-- For Shiro -->
+            <groupId>org.slf4j</groupId>
+            <artifactId>jcl-over-slf4j</artifactId>
+        </dependency>
+        <dependency>
             <groupId>org.slf4j</groupId>
             <artifactId>slf4j-api</artifactId>
         </dependency>
diff --git a/util/src/main/java/com/ning/billing/util/callcontext/DefaultTenantContext.java b/util/src/main/java/com/ning/billing/util/callcontext/DefaultTenantContext.java
index 4d072d2..a6dbf20 100644
--- a/util/src/main/java/com/ning/billing/util/callcontext/DefaultTenantContext.java
+++ b/util/src/main/java/com/ning/billing/util/callcontext/DefaultTenantContext.java
@@ -24,10 +24,6 @@ public class DefaultTenantContext implements TenantContext {
 
     private final UUID tenantId;
 
-    public DefaultTenantContext() {
-        this(null);
-    }
-
     public DefaultTenantContext(@Nullable final UUID tenantId) {
         this.tenantId = tenantId;
     }
diff --git a/util/src/main/java/com/ning/billing/util/callcontext/InternalTenantContext.java b/util/src/main/java/com/ning/billing/util/callcontext/InternalTenantContext.java
index 5454264..7dacd5e 100644
--- a/util/src/main/java/com/ning/billing/util/callcontext/InternalTenantContext.java
+++ b/util/src/main/java/com/ning/billing/util/callcontext/InternalTenantContext.java
@@ -16,6 +16,8 @@
 
 package com.ning.billing.util.callcontext;
 
+import java.util.UUID;
+
 import javax.annotation.Nullable;
 
 /**
@@ -35,8 +37,8 @@ public class InternalTenantContext {
         this(defaultTenantRecordId, null);
     }
 
-    public TenantContext toTenantContext() {
-        return new DefaultTenantContext();
+    public TenantContext toTenantContext(final UUID tenantId) {
+        return new DefaultTenantContext(tenantId);
     }
 
     public Long getAccountRecordId() {
diff --git a/util/src/main/java/com/ning/billing/util/config/SecurityConfig.java b/util/src/main/java/com/ning/billing/util/config/SecurityConfig.java
new file mode 100644
index 0000000..0af56b2
--- /dev/null
+++ b/util/src/main/java/com/ning/billing/util/config/SecurityConfig.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2010-2013 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.config;
+
+import org.skife.config.Config;
+import org.skife.config.Default;
+import org.skife.config.DefaultNull;
+import org.skife.config.Description;
+
+public interface SecurityConfig extends KillbillConfig {
+
+    @Config("killbill.security.shiroResourcePath")
+    @Default("classpath:shiro.ini")
+    @Description("Path to the shiro.ini file (classpath, url or file resource)")
+    public String getShiroResourcePath();
+
+    // LDAP Realm
+
+    @Config("killbill.security.ldap.userDnTemplate")
+    @DefaultNull
+    @Description("LDAP server's User DN format (e.g. uid={0},ou=users,dc=mycompany,dc=com)")
+    public String getShiroLDAPUserDnTemplate();
+
+    @Config("killbill.security.ldap.searchBase")
+    @DefaultNull
+    @Description("LDAP search base to use")
+    public String getShiroLDAPSearchBase();
+
+    @Config("killbill.security.ldap.groupSearchFilter")
+    @Default("memberOf=uid={0}")
+    @Description("LDAP search filter to use to find groups (e.g. memberOf=uid={0},ou=users,dc=mycompany,dc=com)")
+    public String getShiroLDAPGroupSearchFilter();
+
+    @Config("killbill.security.ldap.groupNameId")
+    @Default("memberOf")
+    @Description("Group name attribute ID in LDAP")
+    public String getShiroLDAPGroupNameID();
+
+    @Config("killbill.security.ldap.permissionsByGroup")
+    @Default("admin = *:*\n" +
+             "finance = invoice:*, payment:*\n" +
+             "support = entitlement:*, invoice:item_adjust")
+    @Description("LDAP permissions by LDAP group")
+    public String getShiroLDAPPermissionsByGroup();
+
+    @Config("killbill.security.ldap.url")
+    @Default("ldap://127.0.0.1:389")
+    @Description("LDAP server url")
+    public String getShiroLDAPUrl();
+
+    @Config("killbill.security.ldap.systemUsername")
+    @DefaultNull
+    @Description("LDAP username")
+    public String getShiroLDAPSystemUsername();
+
+    @Config("killbill.security.ldap.systemPassword")
+    @DefaultNull
+    @Description("LDAP password")
+    public String getShiroLDAPSystemPassword();
+
+    @Config("killbill.security.ldap.authenticationMechanism")
+    @Default("simple")
+    @Description("LDAP authentication mechanism (e.g. DIGEST-MD5)")
+    public String getShiroLDAPAuthenticationMechanism();
+
+    @Config("killbill.security.ldap.disableSSLCheck")
+    @Default("false")
+    @Description("Whether to ignore SSL certificates checks")
+    public boolean disableShiroLDAPSSLCheck();
+}
diff --git a/util/src/main/java/com/ning/billing/util/dao/DefaultNonEntityDao.java b/util/src/main/java/com/ning/billing/util/dao/DefaultNonEntityDao.java
index 232983e..5631dbc 100644
--- a/util/src/main/java/com/ning/billing/util/dao/DefaultNonEntityDao.java
+++ b/util/src/main/java/com/ning/billing/util/dao/DefaultNonEntityDao.java
@@ -103,6 +103,11 @@ public class DefaultNonEntityDao implements NonEntityDao {
         return nonEntitySqlDao.getHistoryTargetRecordId(recordId, tableName.getTableName());
     }
 
+    @Override
+    public UUID retrieveIdFromObject(final Long recordId, final ObjectType objectType) {
+        final TableName tableName = TableName.fromObjectType(objectType);
+        return nonEntitySqlDao.getIdFromObject(recordId, tableName.getTableName());
+    }
 
     private interface OperationRetrieval<T> {
         public T doRetrieve(final UUID objectId, final ObjectType objectType);
diff --git a/util/src/main/java/com/ning/billing/util/dao/NonEntityDao.java b/util/src/main/java/com/ning/billing/util/dao/NonEntityDao.java
index 26be4a4..58f7ae3 100644
--- a/util/src/main/java/com/ning/billing/util/dao/NonEntityDao.java
+++ b/util/src/main/java/com/ning/billing/util/dao/NonEntityDao.java
@@ -39,6 +39,8 @@ public interface NonEntityDao {
     // This retrieves from the history table the latest record for which targetId matches the one we are passing
     public Long retrieveLastHistoryRecordIdFromTransaction(final Long targetRecordId, final TableName tableName, final NonEntitySqlDao transactional);
 
-    //This is the reverse from retrieveLastHistoryRecordIdFromTransaction; this retrieves the record_id of the object matching a given history row
+    // This is the reverse from retrieveLastHistoryRecordIdFromTransaction; this retrieves the record_id of the object matching a given history row
     public Long retrieveHistoryTargetRecordId(final Long recordId, final TableName tableName);
+
+    public UUID retrieveIdFromObject(final Long recordId, final ObjectType objectType);
 }
diff --git a/util/src/main/java/com/ning/billing/util/dao/NonEntitySqlDao.java b/util/src/main/java/com/ning/billing/util/dao/NonEntitySqlDao.java
index f0a119d..36d7811 100644
--- a/util/src/main/java/com/ning/billing/util/dao/NonEntitySqlDao.java
+++ b/util/src/main/java/com/ning/billing/util/dao/NonEntitySqlDao.java
@@ -16,6 +16,8 @@
 
 package com.ning.billing.util.dao;
 
+import java.util.UUID;
+
 import org.skife.jdbi.v2.sqlobject.Bind;
 import org.skife.jdbi.v2.sqlobject.SqlQuery;
 import org.skife.jdbi.v2.sqlobject.customizers.Define;
@@ -30,6 +32,9 @@ public interface NonEntitySqlDao extends Transactional<NonEntitySqlDao>, CloseMe
     public Long getRecordIdFromObject(@Bind("id") String id, @Define("tableName") final String tableName);
 
     @SqlQuery
+    public UUID getIdFromObject(@Bind("recordId") Long recordId, @Define("tableName") final String tableName);
+
+    @SqlQuery
     public Long getAccountRecordIdFromAccount(@Bind("id") String id);
 
     @SqlQuery
diff --git a/util/src/main/java/com/ning/billing/util/glue/EhCacheManagerProvider.java b/util/src/main/java/com/ning/billing/util/glue/EhCacheManagerProvider.java
new file mode 100644
index 0000000..bb774d9
--- /dev/null
+++ b/util/src/main/java/com/ning/billing/util/glue/EhCacheManagerProvider.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2010-2013 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.glue;
+
+import javax.inject.Inject;
+import javax.inject.Provider;
+
+import org.apache.shiro.cache.ehcache.EhCacheManager;
+import org.apache.shiro.mgt.DefaultSecurityManager;
+import org.apache.shiro.mgt.SecurityManager;
+
+import net.sf.ehcache.CacheManager;
+
+public class EhCacheManagerProvider implements Provider<EhCacheManager> {
+
+    private final SecurityManager securityManager;
+    private final CacheManager ehCacheCacheManager;
+
+    @Inject
+    public EhCacheManagerProvider(final SecurityManager securityManager, final CacheManager ehCacheCacheManager) {
+        this.securityManager = securityManager;
+        this.ehCacheCacheManager = ehCacheCacheManager;
+    }
+
+    @Override
+    public EhCacheManager get() {
+        final EhCacheManager shiroEhCacheManager = new EhCacheManager();
+        // Same EhCache manager instance as the rest of the system
+        shiroEhCacheManager.setCacheManager(ehCacheCacheManager);
+
+        if (securityManager instanceof DefaultSecurityManager) {
+            ((DefaultSecurityManager) securityManager).setCacheManager(shiroEhCacheManager);
+        }
+
+        return shiroEhCacheManager;
+    }
+}
diff --git a/util/src/main/java/com/ning/billing/util/glue/GlobalLockerModule.java b/util/src/main/java/com/ning/billing/util/glue/GlobalLockerModule.java
index c0245ac..b32bce2 100644
--- a/util/src/main/java/com/ning/billing/util/glue/GlobalLockerModule.java
+++ b/util/src/main/java/com/ning/billing/util/glue/GlobalLockerModule.java
@@ -16,8 +16,7 @@
 
 package com.ning.billing.util.glue;
 
-import com.ning.billing.util.globallocker.GlobalLocker;
-import com.ning.billing.util.globallocker.MySqlGlobalLocker;
+import com.ning.billing.commons.locker.GlobalLocker;
 
 import com.google.inject.AbstractModule;
 
@@ -25,6 +24,6 @@ public class GlobalLockerModule extends AbstractModule {
 
     @Override
     protected void configure() {
-        bind(GlobalLocker.class).to(MySqlGlobalLocker.class).asEagerSingleton();
+        bind(GlobalLocker.class).toProvider(MySqlGlobalLockerProvider.class).asEagerSingleton();
     }
 }
diff --git a/util/src/main/java/com/ning/billing/util/glue/IniRealmProvider.java b/util/src/main/java/com/ning/billing/util/glue/IniRealmProvider.java
new file mode 100644
index 0000000..a124d6d
--- /dev/null
+++ b/util/src/main/java/com/ning/billing/util/glue/IniRealmProvider.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2010-2013 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.glue;
+
+import javax.inject.Inject;
+import javax.inject.Provider;
+
+import org.apache.shiro.config.ConfigurationException;
+import org.apache.shiro.realm.text.IniRealm;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.ning.billing.util.config.SecurityConfig;
+
+public class IniRealmProvider implements Provider<IniRealm> {
+
+    private static final Logger log = LoggerFactory.getLogger(IniRealmProvider.class);
+
+    private final SecurityConfig securityConfig;
+
+    @Inject
+    public IniRealmProvider(final SecurityConfig securityConfig) {
+        this.securityConfig = securityConfig;
+    }
+
+    @Override
+    public IniRealm get() {
+        try {
+            return new IniRealm(securityConfig.getShiroResourcePath());
+        } catch (ConfigurationException e) {
+            log.warn("Unable to configure RBAC", e);
+            return new IniRealm();
+        }
+    }
+}
diff --git a/util/src/main/java/com/ning/billing/util/glue/JDBCSessionDaoProvider.java b/util/src/main/java/com/ning/billing/util/glue/JDBCSessionDaoProvider.java
new file mode 100644
index 0000000..de5299a
--- /dev/null
+++ b/util/src/main/java/com/ning/billing/util/glue/JDBCSessionDaoProvider.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2010-2013 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.glue;
+
+import javax.inject.Inject;
+import javax.inject.Provider;
+
+import org.apache.shiro.session.mgt.DefaultSessionManager;
+import org.apache.shiro.session.mgt.SessionManager;
+import org.skife.jdbi.v2.IDBI;
+
+import com.ning.billing.util.security.shiro.dao.JDBCSessionDao;
+
+public class JDBCSessionDaoProvider implements Provider<JDBCSessionDao> {
+
+    private final SessionManager sessionManager;
+    private final IDBI dbi;
+
+    @Inject
+    public JDBCSessionDaoProvider(final IDBI dbi, final SessionManager sessionManager) {
+        this.sessionManager = sessionManager;
+        this.dbi = dbi;
+    }
+
+    @Override
+    public JDBCSessionDao get() {
+        final JDBCSessionDao jdbcSessionDao = new JDBCSessionDao(dbi);
+
+        if (sessionManager instanceof DefaultSessionManager) {
+            ((DefaultSessionManager) sessionManager).setSessionDAO(jdbcSessionDao);
+        }
+
+        return jdbcSessionDao;
+    }
+}
diff --git a/util/src/main/java/com/ning/billing/util/glue/KillBillShiroAopModule.java b/util/src/main/java/com/ning/billing/util/glue/KillBillShiroAopModule.java
new file mode 100644
index 0000000..d3611ae
--- /dev/null
+++ b/util/src/main/java/com/ning/billing/util/glue/KillBillShiroAopModule.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2010-2013 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.glue;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+
+import org.apache.shiro.aop.AnnotationMethodInterceptor;
+import org.apache.shiro.aop.AnnotationResolver;
+import org.apache.shiro.guice.aop.ShiroAopModule;
+
+import com.ning.billing.util.security.AnnotationHierarchicalResolver;
+import com.ning.billing.util.security.AopAllianceMethodInterceptorAdapter;
+import com.ning.billing.util.security.PermissionAnnotationHandler;
+import com.ning.billing.util.security.PermissionAnnotationMethodInterceptor;
+
+import com.google.inject.matcher.AbstractMatcher;
+import com.google.inject.matcher.Matchers;
+
+// Provides authentication via Shiro
+public class KillBillShiroAopModule extends ShiroAopModule {
+
+    private final AnnotationHierarchicalResolver resolver = new AnnotationHierarchicalResolver();
+
+    @Override
+    protected AnnotationResolver createAnnotationResolver() {
+        return resolver;
+    }
+
+    @Override
+    protected void configureInterceptors(final AnnotationResolver resolver) {
+        super.configureInterceptors(resolver);
+
+        if (!KillBillShiroModule.isRBACEnabled()) {
+            return;
+        }
+
+        final PermissionAnnotationHandler permissionAnnotationHandler = new PermissionAnnotationHandler();
+        // Inject the Security API
+        requestInjection(permissionAnnotationHandler);
+
+        final PermissionAnnotationMethodInterceptor methodInterceptor = new PermissionAnnotationMethodInterceptor(permissionAnnotationHandler, resolver);
+        bindShiroInterceptorWithHierarchy(methodInterceptor);
+    }
+
+    // Similar to bindShiroInterceptor but will look for annotations in the class hierarchy
+    protected final void bindShiroInterceptorWithHierarchy(final AnnotationMethodInterceptor methodInterceptor) {
+        bindInterceptor(Matchers.any(),
+                        new AbstractMatcher<Method>() {
+                            public boolean matches(final Method method) {
+                                final Class<? extends Annotation> annotation = methodInterceptor.getHandler().getAnnotationClass();
+                                return resolver.getAnnotationFromMethod(method, annotation) != null;
+                            }
+                        },
+                        new AopAllianceMethodInterceptorAdapter(methodInterceptor));
+    }
+}
diff --git a/util/src/main/java/com/ning/billing/util/glue/KillBillShiroModule.java b/util/src/main/java/com/ning/billing/util/glue/KillBillShiroModule.java
new file mode 100644
index 0000000..ee99ac1
--- /dev/null
+++ b/util/src/main/java/com/ning/billing/util/glue/KillBillShiroModule.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2010-2013 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.glue;
+
+import org.apache.shiro.cache.CacheManager;
+import org.apache.shiro.guice.ShiroModule;
+import org.apache.shiro.mgt.SecurityManager;
+import org.apache.shiro.session.mgt.DefaultSessionManager;
+import org.apache.shiro.session.mgt.SessionManager;
+
+import com.ning.billing.util.security.shiro.dao.JDBCSessionDao;
+import com.ning.billing.util.security.shiro.realm.KillBillJndiLdapRealm;
+
+import com.google.inject.binder.AnnotatedBindingBuilder;
+
+// For Kill Bill library only.
+// See com.ning.billing.server.modules.KillBillShiroWebModule for Kill Bill server.
+public class KillBillShiroModule extends ShiroModule {
+
+    public static final String KILLBILL_LDAP_PROPERTY = "killbill.server.ldap";
+    public static final String KILLBILL_RBAC_PROPERTY = "killbill.server.rbac";
+
+    public static boolean isLDAPEnabled() {
+        return Boolean.parseBoolean(System.getProperty(KILLBILL_LDAP_PROPERTY, "false"));
+    }
+
+    public static boolean isRBACEnabled() {
+        return Boolean.parseBoolean(System.getProperty(KILLBILL_RBAC_PROPERTY, "true"));
+    }
+
+    protected void configureShiro() {
+        bindRealm().toProvider(IniRealmProvider.class).asEagerSingleton();
+
+        if (isLDAPEnabled()) {
+            bindRealm().to(KillBillJndiLdapRealm.class).asEagerSingleton();
+        }
+    }
+
+    @Override
+    protected void bindSecurityManager(final AnnotatedBindingBuilder<? super SecurityManager> bind) {
+        super.bindSecurityManager(bind);
+
+        // Magic provider to configure the cache manager
+        bind(CacheManager.class).toProvider(EhCacheManagerProvider.class).asEagerSingleton();
+    }
+
+    @Override
+    protected void bindSessionManager(final AnnotatedBindingBuilder<SessionManager> bind) {
+        bind.to(DefaultSessionManager.class).asEagerSingleton();
+
+        // Magic provider to configure the session DAO
+        bind(JDBCSessionDao.class).toProvider(JDBCSessionDaoProvider.class).asEagerSingleton();
+    }
+}
diff --git a/util/src/main/java/com/ning/billing/util/glue/SecurityModule.java b/util/src/main/java/com/ning/billing/util/glue/SecurityModule.java
new file mode 100644
index 0000000..a8ea01a
--- /dev/null
+++ b/util/src/main/java/com/ning/billing/util/glue/SecurityModule.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2010-2013 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.glue;
+
+import org.skife.config.ConfigSource;
+import org.skife.config.ConfigurationObjectFactory;
+import org.skife.config.SimplePropertyConfigSource;
+
+import com.ning.billing.security.api.SecurityApi;
+import com.ning.billing.util.config.SecurityConfig;
+import com.ning.billing.util.security.api.DefaultSecurityApi;
+import com.ning.billing.util.security.api.DefaultSecurityService;
+import com.ning.billing.util.security.api.SecurityService;
+
+import com.google.inject.AbstractModule;
+
+public class SecurityModule extends AbstractModule {
+
+    private final ConfigSource configSource;
+
+    public SecurityModule() {
+        this(new SimplePropertyConfigSource(System.getProperties()));
+    }
+
+    public SecurityModule(final ConfigSource configSource) {
+        this.configSource = configSource;
+    }
+
+    public void configure() {
+        installConfig();
+        installSecurityApi();
+        installSecurityService();
+    }
+
+    private void installConfig() {
+        final SecurityConfig securityConfig = new ConfigurationObjectFactory(configSource).build(SecurityConfig.class);
+        bind(SecurityConfig.class).toInstance(securityConfig);
+    }
+
+    private void installSecurityApi() {
+        bind(SecurityApi.class).to(DefaultSecurityApi.class).asEagerSingleton();
+    }
+
+    protected void installSecurityService() {
+        bind(SecurityService.class).to(DefaultSecurityService.class).asEagerSingleton();
+    }
+}
diff --git a/util/src/main/java/com/ning/billing/util/security/AnnotationHierarchicalResolver.java b/util/src/main/java/com/ning/billing/util/security/AnnotationHierarchicalResolver.java
new file mode 100644
index 0000000..0f7b563
--- /dev/null
+++ b/util/src/main/java/com/ning/billing/util/security/AnnotationHierarchicalResolver.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright 2010-2013 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.security;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import java.util.Map;
+import java.util.WeakHashMap;
+
+import org.apache.shiro.aop.AnnotationResolver;
+import org.apache.shiro.aop.MethodInvocation;
+
+public class AnnotationHierarchicalResolver implements AnnotationResolver {
+
+    @Override
+    public Annotation getAnnotation(final MethodInvocation mi, final Class<? extends Annotation> clazz) {
+        return getAnnotationFromMethod(mi.getMethod(), clazz);
+    }
+
+    public Annotation getAnnotationFromMethod(final Method method, final Class<? extends Annotation> clazz) {
+        return findAnnotation(method, clazz);
+    }
+
+    // The following comes from spring-core (AnnotationUtils) to handle annotations on interfaces
+
+    /**
+     * Get a single {@link Annotation} of <code>annotationType</code> from the supplied {@link java.lang.reflect.Method},
+     * traversing its super methods if no annotation can be found on the given method itself.
+     * <p>Annotations on methods are not inherited by default, so we need to handle this explicitly.
+     *
+     * @param method         the method to look for annotations on
+     * @param annotationType the annotation class to look for
+     * @return the annotation found, or <code>null</code> if none found
+     */
+    public static <A extends Annotation> A findAnnotation(final Method method, final Class<A> annotationType) {
+        A annotation = getAnnotation(method, annotationType);
+        Class<?> cl = method.getDeclaringClass();
+        if (annotation == null) {
+            annotation = searchOnInterfaces(method, annotationType, cl.getInterfaces());
+        }
+        while (annotation == null) {
+            cl = cl.getSuperclass();
+            if (cl == null || cl == Object.class) {
+                break;
+            }
+            try {
+                final Method equivalentMethod = cl.getDeclaredMethod(method.getName(), method.getParameterTypes());
+                annotation = getAnnotation(equivalentMethod, annotationType);
+                if (annotation == null) {
+                    annotation = searchOnInterfaces(method, annotationType, cl.getInterfaces());
+                }
+            } catch (NoSuchMethodException ex) {
+                // We're done...
+            }
+        }
+        return annotation;
+    }
+
+    /**
+     * Get a single {@link Annotation} of <code>annotationType</code> from the supplied {@link Method}.
+     *
+     * @param method         the method to look for annotations on
+     * @param annotationType the annotation class to look for
+     * @return the annotations found
+     */
+    public static <A extends Annotation> A getAnnotation(final Method method, final Class<A> annotationType) {
+        A ann = method.getAnnotation(annotationType);
+        if (ann == null) {
+            for (final Annotation metaAnn : method.getAnnotations()) {
+                ann = metaAnn.annotationType().getAnnotation(annotationType);
+                if (ann != null) {
+                    break;
+                }
+            }
+        }
+        return ann;
+    }
+
+    private static <A extends Annotation> A searchOnInterfaces(final Method method, final Class<A> annotationType, final Class<?>[] ifcs) {
+        A annotation = null;
+        for (final Class<?> iface : ifcs) {
+            if (isInterfaceWithAnnotatedMethods(iface)) {
+                try {
+                    final Method equivalentMethod = iface.getMethod(method.getName(), method.getParameterTypes());
+                    annotation = getAnnotation(equivalentMethod, annotationType);
+                } catch (NoSuchMethodException ex) {
+                    // Skip this interface - it doesn't have the method...
+                }
+                if (annotation != null) {
+                    break;
+                }
+            }
+        }
+        return annotation;
+    }
+
+    private static final Map<Class<?>, Boolean> annotatedInterfaceCache = new WeakHashMap<Class<?>, Boolean>();
+
+    private static boolean isInterfaceWithAnnotatedMethods(final Class<?> iface) {
+        synchronized (annotatedInterfaceCache) {
+            final Boolean flag = annotatedInterfaceCache.get(iface);
+            if (flag != null) {
+                return flag;
+            }
+            boolean found = false;
+            for (final Method ifcMethod : iface.getMethods()) {
+                if (ifcMethod.getAnnotations().length > 0) {
+                    found = true;
+                    break;
+                }
+            }
+            annotatedInterfaceCache.put(iface, found);
+            return found;
+        }
+    }
+}
diff --git a/util/src/main/java/com/ning/billing/util/security/AopAllianceMethodInvocationAdapter.java b/util/src/main/java/com/ning/billing/util/security/AopAllianceMethodInvocationAdapter.java
new file mode 100644
index 0000000..1b93956
--- /dev/null
+++ b/util/src/main/java/com/ning/billing/util/security/AopAllianceMethodInvocationAdapter.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2010-2013 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.security;
+
+import java.lang.reflect.Method;
+
+import org.aopalliance.intercept.MethodInvocation;
+
+// Taken from Shiro - the original class is private :(
+public class AopAllianceMethodInvocationAdapter implements org.apache.shiro.aop.MethodInvocation {
+
+    private final MethodInvocation mi;
+
+    public AopAllianceMethodInvocationAdapter(final MethodInvocation mi) {
+        this.mi = mi;
+    }
+
+    public Method getMethod() {
+        return mi.getMethod();
+    }
+
+    public Object[] getArguments() {
+        return mi.getArguments();
+    }
+
+    public String toString() {
+        return "Method invocation [" + mi.getMethod() + "]";
+    }
+
+    public Object proceed() throws Throwable {
+        return mi.proceed();
+    }
+
+    public Object getThis() {
+        return mi.getThis();
+    }
+}
diff --git a/util/src/main/java/com/ning/billing/util/security/api/DefaultSecurityApi.java b/util/src/main/java/com/ning/billing/util/security/api/DefaultSecurityApi.java
new file mode 100644
index 0000000..efddf40
--- /dev/null
+++ b/util/src/main/java/com/ning/billing/util/security/api/DefaultSecurityApi.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2010-2013 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.security.api;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.shiro.SecurityUtils;
+import org.apache.shiro.authz.AuthorizationException;
+import org.apache.shiro.subject.Subject;
+
+import com.ning.billing.ErrorCode;
+import com.ning.billing.security.Logical;
+import com.ning.billing.security.Permission;
+import com.ning.billing.security.SecurityApiException;
+import com.ning.billing.security.api.SecurityApi;
+import com.ning.billing.util.callcontext.TenantContext;
+
+import com.google.common.base.Functions;
+import com.google.common.collect.Lists;
+
+public class DefaultSecurityApi implements SecurityApi {
+
+    private static final String[] allPermissions = new String[Permission.values().length];
+
+    @Override
+    public Set<Permission> getCurrentUserPermissions(final TenantContext context) {
+        final Permission[] killbillPermissions = Permission.values();
+        final String[] killbillPermissionsString = getAllPermissionsAsStrings();
+
+        final Subject subject = SecurityUtils.getSubject();
+        // Bulk (optimized) call
+        final boolean[] permissions = subject.isPermitted(killbillPermissionsString);
+
+        final Set<Permission> userPermissions = new HashSet<Permission>();
+        for (int i = 0; i < permissions.length; i++) {
+            if (permissions[i]) {
+                userPermissions.add(killbillPermissions[i]);
+            }
+        }
+
+        return userPermissions;
+    }
+
+    @Override
+    public void checkCurrentUserPermissions(final List<Permission> permissions, final Logical logical, final TenantContext context) throws SecurityApiException {
+        final String[] permissionsString = Lists.<Permission, String>transform(permissions, Functions.toStringFunction()).toArray(new String[permissions.size()]);
+
+        try {
+            final Subject subject = SecurityUtils.getSubject();
+            if (permissionsString.length == 1) {
+                subject.checkPermission(permissionsString[0]);
+            } else if (Logical.AND.equals(logical)) {
+                subject.checkPermissions(permissionsString);
+            } else if (Logical.OR.equals(logical)) {
+                boolean hasAtLeastOnePermission = false;
+                for (final String permission : permissionsString) {
+                    if (subject.isPermitted(permission)) {
+                        hasAtLeastOnePermission = true;
+                        break;
+                    }
+                }
+
+                // Cause the exception if none match
+                if (!hasAtLeastOnePermission) {
+                    subject.checkPermission(permissionsString[0]);
+                }
+            }
+        } catch (AuthorizationException e) {
+            throw new SecurityApiException(e, ErrorCode.SECURITY_NOT_ENOUGH_PERMISSIONS);
+        }
+    }
+
+    private String[] getAllPermissionsAsStrings() {
+        if (allPermissions[0] == null) {
+            synchronized (allPermissions) {
+                if (allPermissions[0] == null) {
+                    final Permission[] killbillPermissions = Permission.values();
+                    for (int i = 0; i < killbillPermissions.length; i++) {
+                        allPermissions[i] = killbillPermissions[i].toString();
+                    }
+                }
+            }
+        }
+
+        return allPermissions;
+    }
+}
diff --git a/util/src/main/java/com/ning/billing/util/security/api/DefaultSecurityService.java b/util/src/main/java/com/ning/billing/util/security/api/DefaultSecurityService.java
new file mode 100644
index 0000000..9b92a65
--- /dev/null
+++ b/util/src/main/java/com/ning/billing/util/security/api/DefaultSecurityService.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2010-2013 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.security.api;
+
+import javax.inject.Inject;
+
+import org.apache.shiro.SecurityUtils;
+import org.apache.shiro.mgt.SecurityManager;
+
+import com.ning.billing.lifecycle.LifecycleHandlerType;
+import com.ning.billing.lifecycle.LifecycleHandlerType.LifecycleLevel;
+
+public class DefaultSecurityService implements SecurityService {
+
+    public static final String SECURITY_SERVICE_NAME = "security-service";
+
+    private final SecurityManager securityManager;
+
+    @Inject
+    public DefaultSecurityService(final SecurityManager securityManager) {
+        this.securityManager = securityManager;
+    }
+
+    @Override
+    public String getName() {
+        return SECURITY_SERVICE_NAME;
+    }
+
+    @LifecycleHandlerType(LifecycleHandlerType.LifecycleLevel.INIT_SERVICE)
+    public void initialize() {
+        SecurityUtils.setSecurityManager(securityManager);
+    }
+
+    @LifecycleHandlerType(LifecycleLevel.STOP_SERVICE)
+    public void stop() {
+        SecurityUtils.setSecurityManager(null);
+    }
+}
diff --git a/util/src/main/java/com/ning/billing/util/security/PermissionAnnotationHandler.java b/util/src/main/java/com/ning/billing/util/security/PermissionAnnotationHandler.java
new file mode 100644
index 0000000..88551ab
--- /dev/null
+++ b/util/src/main/java/com/ning/billing/util/security/PermissionAnnotationHandler.java
@@ -0,0 +1,67 @@
+package com.ning.billing.util.security;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF 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.
+ */
+
+import java.lang.annotation.Annotation;
+
+import javax.inject.Inject;
+
+import org.apache.shiro.authz.AuthorizationException;
+import org.apache.shiro.authz.aop.AuthorizingAnnotationHandler;
+
+import com.ning.billing.security.Permission;
+import com.ning.billing.security.RequiresPermissions;
+import com.ning.billing.security.SecurityApiException;
+import com.ning.billing.security.api.SecurityApi;
+import com.ning.billing.util.callcontext.DefaultTenantContext;
+import com.ning.billing.util.callcontext.TenantContext;
+
+import com.google.common.collect.ImmutableList;
+
+public class PermissionAnnotationHandler extends AuthorizingAnnotationHandler {
+
+    private final TenantContext context = new DefaultTenantContext(null);
+
+    @Inject
+    SecurityApi securityApi;
+
+    public PermissionAnnotationHandler() {
+        super(RequiresPermissions.class);
+    }
+
+    public void assertAuthorized(final Annotation annotation) throws AuthorizationException {
+        if (!(annotation instanceof RequiresPermissions)) {
+            return;
+        }
+
+        final RequiresPermissions requiresPermissions = (RequiresPermissions) annotation;
+        try {
+            securityApi.checkCurrentUserPermissions(ImmutableList.<Permission>copyOf(requiresPermissions.value()), requiresPermissions.logical(), context);
+        } catch (SecurityApiException e) {
+            if (e.getCause() != null && e.getCause() instanceof AuthorizationException) {
+                throw (AuthorizationException) e.getCause();
+            } else if (e.getCause() != null) {
+                throw new AuthorizationException(e.getCause());
+            } else {
+                throw new AuthorizationException(e);
+            }
+        }
+    }
+}
diff --git a/util/src/main/java/com/ning/billing/util/security/shiro/dao/JDBCSessionDao.java b/util/src/main/java/com/ning/billing/util/security/shiro/dao/JDBCSessionDao.java
new file mode 100644
index 0000000..3dbec52
--- /dev/null
+++ b/util/src/main/java/com/ning/billing/util/security/shiro/dao/JDBCSessionDao.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2010-2013 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.security.shiro.dao;
+
+import java.io.IOException;
+import java.io.Serializable;
+
+import javax.inject.Inject;
+
+import org.apache.shiro.session.Session;
+import org.apache.shiro.session.mgt.eis.CachingSessionDAO;
+import org.skife.jdbi.v2.DBI;
+import org.skife.jdbi.v2.IDBI;
+import org.skife.jdbi.v2.Transaction;
+import org.skife.jdbi.v2.TransactionStatus;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.ning.billing.commons.jdbi.mapper.LowerToCamelBeanMapperFactory;
+
+public class JDBCSessionDao extends CachingSessionDAO {
+
+    private static final Logger log = LoggerFactory.getLogger(JDBCSessionDao.class);
+
+    private JDBCSessionSqlDao jdbcSessionSqlDao;
+
+    @Inject
+    public JDBCSessionDao(final IDBI dbi) {
+        if (dbi instanceof DBI) {
+            // TODO PIERRE Move to DBIProvider, once it's in util
+            ((DBI) dbi).registerMapper(new LowerToCamelBeanMapperFactory(SessionModelDao.class));
+        }
+        this.jdbcSessionSqlDao = dbi.onDemand(JDBCSessionSqlDao.class);
+    }
+
+    @Override
+    protected void doUpdate(final Session session) {
+        jdbcSessionSqlDao.update(new SessionModelDao(session));
+    }
+
+    @Override
+    protected void doDelete(final Session session) {
+        jdbcSessionSqlDao.delete(new SessionModelDao(session));
+    }
+
+    @Override
+    protected Serializable doCreate(final Session session) {
+        final Serializable sessionId = jdbcSessionSqlDao.inTransaction(new Transaction<Long, JDBCSessionSqlDao>() {
+            @Override
+            public Long inTransaction(final JDBCSessionSqlDao transactional, final TransactionStatus status) throws Exception {
+                transactional.create(new SessionModelDao(session));
+                return transactional.getLastInsertId();
+            }
+        });
+        assignSessionId(session, sessionId);
+        return sessionId;
+    }
+
+    @Override
+    protected Session doReadSession(final Serializable sessionId) {
+        final SessionModelDao sessionModelDao = jdbcSessionSqlDao.read(sessionId);
+        if (sessionModelDao == null) {
+            return null;
+        }
+
+        try {
+            return sessionModelDao.toSimpleSession();
+        } catch (IOException e) {
+            log.warn("Corrupted cookie", e);
+            return null;
+        }
+    }
+}
diff --git a/util/src/main/java/com/ning/billing/util/security/shiro/dao/JDBCSessionSqlDao.java b/util/src/main/java/com/ning/billing/util/security/shiro/dao/JDBCSessionSqlDao.java
new file mode 100644
index 0000000..cdd8e0a
--- /dev/null
+++ b/util/src/main/java/com/ning/billing/util/security/shiro/dao/JDBCSessionSqlDao.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2010-2013 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.security.shiro.dao;
+
+import java.io.Serializable;
+
+import org.skife.jdbi.v2.sqlobject.Bind;
+import org.skife.jdbi.v2.sqlobject.SqlQuery;
+import org.skife.jdbi.v2.sqlobject.SqlUpdate;
+import org.skife.jdbi.v2.sqlobject.mixins.Transactional;
+import org.skife.jdbi.v2.sqlobject.stringtemplate.UseStringTemplate3StatementLocator;
+
+import com.ning.billing.commons.jdbi.binder.SmartBindBean;
+
+@UseStringTemplate3StatementLocator
+public interface JDBCSessionSqlDao extends Transactional<JDBCSessionSqlDao> {
+
+    @SqlQuery
+    public SessionModelDao read(@Bind("recordId") final Serializable sessionId);
+
+    @SqlUpdate
+    public void create(@SmartBindBean final SessionModelDao sessionModelDao);
+
+    @SqlUpdate
+    public void update(@SmartBindBean final SessionModelDao sessionModelDao);
+
+    @SqlUpdate
+    public void delete(@SmartBindBean final SessionModelDao sessionModelDao);
+
+    @SqlQuery
+    public Long getLastInsertId();
+}
diff --git a/util/src/main/java/com/ning/billing/util/security/shiro/dao/SessionModelDao.java b/util/src/main/java/com/ning/billing/util/security/shiro/dao/SessionModelDao.java
new file mode 100644
index 0000000..30602b2
--- /dev/null
+++ b/util/src/main/java/com/ning/billing/util/security/shiro/dao/SessionModelDao.java
@@ -0,0 +1,161 @@
+/*
+ * Copyright 2010-2013 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.security.shiro.dao;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.shiro.io.DefaultSerializer;
+import org.apache.shiro.io.Serializer;
+import org.apache.shiro.session.Session;
+import org.apache.shiro.session.mgt.SimpleSession;
+import org.joda.time.DateTime;
+import org.joda.time.DateTimeZone;
+
+public class SessionModelDao {
+
+    private final Serializer<Map> serializer = new DefaultSerializer<Map>();
+
+    private Long recordId;
+    private DateTime startTimestamp;
+    private DateTime lastAccessTime;
+    private long timeout;
+    private String host;
+    private byte[] sessionData;
+
+    public SessionModelDao() { /* For the DAO mapper */ }
+
+    public SessionModelDao(final Session session) {
+        this.recordId = (Long) session.getId();
+        this.startTimestamp = new DateTime(session.getStartTimestamp(), DateTimeZone.UTC);
+        this.lastAccessTime = new DateTime(session.getLastAccessTime(), DateTimeZone.UTC);
+        this.timeout = session.getTimeout();
+        this.host = session.getHost();
+        try {
+            this.sessionData = serializeSessionData(session);
+        } catch (IOException e) {
+            this.sessionData = new byte[]{};
+        }
+    }
+
+    public Session toSimpleSession() throws IOException {
+        final SimpleSession simpleSession = new SimpleSession();
+        simpleSession.setId(recordId);
+        simpleSession.setStartTimestamp(startTimestamp.toDate());
+        simpleSession.setLastAccessTime(lastAccessTime.toDate());
+        simpleSession.setTimeout(timeout);
+        simpleSession.setHost(host);
+
+        final Map attributes = serializer.deserialize(sessionData);
+        //noinspection unchecked
+        simpleSession.setAttributes(attributes);
+
+        return simpleSession;
+    }
+
+    public Long getRecordId() {
+        return recordId;
+    }
+
+    public DateTime getStartTimestamp() {
+        return startTimestamp;
+    }
+
+    public DateTime getLastAccessTime() {
+        return lastAccessTime;
+    }
+
+    public long getTimeout() {
+        return timeout;
+    }
+
+    public String getHost() {
+        return host;
+    }
+
+    public byte[] getSessionData() {
+        return sessionData;
+    }
+
+    @Override
+    public String toString() {
+        final StringBuilder sb = new StringBuilder("SessionModelDao{");
+        sb.append("recordId=").append(recordId);
+        sb.append(", startTimestamp=").append(startTimestamp);
+        sb.append(", lastAccessTime=").append(lastAccessTime);
+        sb.append(", timeout=").append(timeout);
+        sb.append(", host='").append(host).append('\'');
+        sb.append(", sessionData=").append(Arrays.toString(sessionData));
+        sb.append('}');
+        return sb.toString();
+    }
+
+    @Override
+    public boolean equals(final Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+
+        final SessionModelDao that = (SessionModelDao) o;
+
+        if (timeout != that.timeout) {
+            return false;
+        }
+        if (host != null ? !host.equals(that.host) : that.host != null) {
+            return false;
+        }
+        if (lastAccessTime != null ? !lastAccessTime.equals(that.lastAccessTime) : that.lastAccessTime != null) {
+            return false;
+        }
+        if (recordId != null ? !recordId.equals(that.recordId) : that.recordId != null) {
+            return false;
+        }
+        if (!Arrays.equals(sessionData, that.sessionData)) {
+            return false;
+        }
+        if (startTimestamp != null ? !startTimestamp.equals(that.startTimestamp) : that.startTimestamp != null) {
+            return false;
+        }
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = recordId != null ? recordId.hashCode() : 0;
+        result = 31 * result + (startTimestamp != null ? startTimestamp.hashCode() : 0);
+        result = 31 * result + (lastAccessTime != null ? lastAccessTime.hashCode() : 0);
+        result = 31 * result + (int) (timeout ^ (timeout >>> 32));
+        result = 31 * result + (host != null ? host.hashCode() : 0);
+        result = 31 * result + (sessionData != null ? Arrays.hashCode(sessionData) : 0);
+        return result;
+    }
+
+    private byte[] serializeSessionData(final Session session) throws IOException {
+        final Map<Object, Object> sessionAttributes = new HashMap<Object, Object>();
+        for (final Object key : session.getAttributeKeys()) {
+            sessionAttributes.put(key, session.getAttribute(key));
+        }
+
+        return serializer.serialize(sessionAttributes);
+    }
+}
diff --git a/util/src/main/java/com/ning/billing/util/security/shiro/realm/KillBillJndiLdapRealm.java b/util/src/main/java/com/ning/billing/util/security/shiro/realm/KillBillJndiLdapRealm.java
new file mode 100644
index 0000000..a4eb644
--- /dev/null
+++ b/util/src/main/java/com/ning/billing/util/security/shiro/realm/KillBillJndiLdapRealm.java
@@ -0,0 +1,222 @@
+/*
+ * Copyright 2010-2013 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.security.shiro.realm;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.directory.Attribute;
+import javax.naming.directory.SearchControls;
+import javax.naming.directory.SearchResult;
+import javax.naming.ldap.LdapContext;
+
+import org.apache.shiro.authc.AuthenticationException;
+import org.apache.shiro.authz.AuthorizationInfo;
+import org.apache.shiro.authz.SimpleAuthorizationInfo;
+import org.apache.shiro.config.Ini;
+import org.apache.shiro.config.Ini.Section;
+import org.apache.shiro.realm.ldap.JndiLdapContextFactory;
+import org.apache.shiro.realm.ldap.JndiLdapRealm;
+import org.apache.shiro.realm.ldap.LdapContextFactory;
+import org.apache.shiro.realm.ldap.LdapUtils;
+import org.apache.shiro.subject.PrincipalCollection;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.ning.billing.util.config.SecurityConfig;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Function;
+import com.google.common.base.Predicate;
+import com.google.common.base.Predicates;
+import com.google.common.base.Splitter;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterators;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+import com.google.inject.Inject;
+
+public class KillBillJndiLdapRealm extends JndiLdapRealm {
+
+    private static final Logger log = LoggerFactory.getLogger(KillBillJndiLdapRealm.class);
+
+    private static final String USERDN_SUBSTITUTION_TOKEN = "{0}";
+
+    private static final SearchControls SUBTREE_SCOPE = new SearchControls();
+
+    static {
+        SUBTREE_SCOPE.setSearchScope(SearchControls.SUBTREE_SCOPE);
+    }
+
+    private static final Splitter SPLITTER = Splitter.on(',').omitEmptyStrings().trimResults();
+
+    private final String searchBase;
+    private final String groupSearchFilter;
+    private final String groupNameId;
+    private final Map<String, Collection<String>> permissionsByGroup = Maps.newLinkedHashMap();
+
+    @Inject
+    public KillBillJndiLdapRealm(final SecurityConfig securityConfig) {
+        super();
+
+        if (securityConfig.getShiroLDAPUserDnTemplate() != null) {
+            setUserDnTemplate(securityConfig.getShiroLDAPUserDnTemplate());
+        }
+
+        final JndiLdapContextFactory contextFactory = (JndiLdapContextFactory) getContextFactory();
+        if (securityConfig.disableShiroLDAPSSLCheck()) {
+            contextFactory.getEnvironment().put("java.naming.ldap.factory.socket", SkipSSLCheckSocketFactory.class.getName());
+        }
+        if (securityConfig.getShiroLDAPUrl() != null) {
+            contextFactory.setUrl(securityConfig.getShiroLDAPUrl());
+        }
+        if (securityConfig.getShiroLDAPSystemUsername() != null) {
+            contextFactory.setSystemUsername(securityConfig.getShiroLDAPSystemUsername());
+        }
+        if (securityConfig.getShiroLDAPSystemPassword() != null) {
+            contextFactory.setSystemPassword(securityConfig.getShiroLDAPSystemPassword());
+        }
+        if (securityConfig.getShiroLDAPAuthenticationMechanism() != null) {
+            contextFactory.setAuthenticationMechanism(securityConfig.getShiroLDAPAuthenticationMechanism());
+        }
+        setContextFactory(contextFactory);
+
+        searchBase = securityConfig.getShiroLDAPSearchBase();
+        groupSearchFilter = securityConfig.getShiroLDAPGroupSearchFilter();
+        groupNameId = securityConfig.getShiroLDAPGroupNameID();
+
+        if (securityConfig.getShiroLDAPPermissionsByGroup() != null) {
+            final Ini ini = new Ini();
+            ini.load(securityConfig.getShiroLDAPPermissionsByGroup());
+            for (final Section section : ini.getSections()) {
+                for (final String role : section.keySet()) {
+                    final Collection<String> permissions = ImmutableList.<String>copyOf(SPLITTER.split(section.get(role)));
+                    permissionsByGroup.put(role, permissions);
+                }
+            }
+        }
+    }
+
+    @Override
+    protected AuthorizationInfo queryForAuthorizationInfo(final PrincipalCollection principals, final LdapContextFactory ldapContextFactory) throws NamingException {
+        final Set<String> userGroups = findLDAPGroupsForUser(principals, ldapContextFactory);
+
+        final SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo(userGroups);
+        final Set<String> stringPermissions = groupsPermissions(userGroups);
+        simpleAuthorizationInfo.setStringPermissions(stringPermissions);
+
+        return simpleAuthorizationInfo;
+    }
+
+    private Set<String> findLDAPGroupsForUser(final PrincipalCollection principals, final LdapContextFactory ldapContextFactory) throws NamingException {
+        final String username = (String) getAvailablePrincipal(principals);
+
+        LdapContext systemLdapCtx = null;
+        try {
+            systemLdapCtx = ldapContextFactory.getSystemLdapContext();
+            return findLDAPGroupsForUser(username, systemLdapCtx);
+        } catch (AuthenticationException ex) {
+            log.info("LDAP authentication exception: " + ex.getLocalizedMessage());
+            return ImmutableSet.<String>of();
+        } finally {
+            LdapUtils.closeContext(systemLdapCtx);
+        }
+    }
+
+    private Set<String> findLDAPGroupsForUser(final String userName, final LdapContext ldapCtx) throws NamingException {
+        final NamingEnumeration<SearchResult> foundGroups = ldapCtx.search(searchBase,
+                                                                           groupSearchFilter.replace(USERDN_SUBSTITUTION_TOKEN, userName),
+                                                                           SUBTREE_SCOPE);
+
+        // Extract the name of all the groups
+        final Iterator<SearchResult> groupsIterator = Iterators.<SearchResult>forEnumeration(foundGroups);
+        final Iterator<String> groupsNameIterator = Iterators.<SearchResult, String>transform(groupsIterator,
+                                                                                              new Function<SearchResult, String>() {
+                                                                                                  @Override
+                                                                                                  public String apply(final SearchResult groupEntry) {
+                                                                                                      return extractGroupNameFromSearchResult(groupEntry);
+                                                                                                  }
+                                                                                              });
+        final Iterator<String> finalGroupsNameIterator = Iterators.<String>filter(groupsNameIterator, Predicates.notNull());
+
+        return Sets.newHashSet(finalGroupsNameIterator);
+    }
+
+    private String extractGroupNameFromSearchResult(final SearchResult searchResult) {
+        // Get all attributes for that group
+        final Iterator<? extends Attribute> attributesIterator = Iterators.forEnumeration(searchResult.getAttributes().getAll());
+
+        // Find the attribute representing the group name
+        final Iterator<? extends Attribute> groupNameAttributesIterator = Iterators.filter(attributesIterator,
+                                                                                           new Predicate<Attribute>() {
+                                                                                               @Override
+                                                                                               public boolean apply(final Attribute attribute) {
+                                                                                                   return groupNameId.equalsIgnoreCase(attribute.getID());
+                                                                                               }
+                                                                                           });
+
+        // Extract the group name from the attribute
+        // Note: at this point, groupNameAttributesIterator should really contain a single element
+        final Iterator<String> groupNamesIterator = Iterators.transform(groupNameAttributesIterator,
+                                                                        new Function<Attribute, String>() {
+                                                                            @Override
+                                                                            public String apply(final Attribute groupNameAttribute) {
+                                                                                try {
+                                                                                    final NamingEnumeration<?> enumeration = groupNameAttribute.getAll();
+                                                                                    if (enumeration.hasMore()) {
+                                                                                        return enumeration.next().toString();
+                                                                                    } else {
+                                                                                        return null;
+                                                                                    }
+                                                                                } catch (NamingException namingException) {
+                                                                                    log.warn("Unable to read group name", namingException);
+                                                                                    return null;
+                                                                                }
+                                                                            }
+                                                                        });
+        final Iterator<String> finalGroupNamesIterator = Iterators.<String>filter(groupNamesIterator, Predicates.notNull());
+
+        if (finalGroupNamesIterator.hasNext()) {
+            return finalGroupNamesIterator.next();
+        } else {
+            log.warn("Unable to find an attribute matching {}", groupNameId);
+            return null;
+        }
+    }
+
+    private Set<String> groupsPermissions(final Set<String> groups) {
+        final Set<String> permissions = new HashSet<String>();
+        for (final String group : groups) {
+            final Collection<String> permissionsForGroup = permissionsByGroup.get(group);
+            if (permissionsForGroup != null) {
+                permissions.addAll(permissionsForGroup);
+            }
+        }
+        return permissions;
+    }
+
+    @VisibleForTesting
+    public Map<String, Collection<String>> getPermissionsByGroup() {
+        return permissionsByGroup;
+    }
+}
diff --git a/util/src/main/java/com/ning/billing/util/security/shiro/realm/SkipSSLCheckSocketFactory.java b/util/src/main/java/com/ning/billing/util/security/shiro/realm/SkipSSLCheckSocketFactory.java
new file mode 100644
index 0000000..d8580e8
--- /dev/null
+++ b/util/src/main/java/com/ning/billing/util/security/shiro/realm/SkipSSLCheckSocketFactory.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2010-2013 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.security.shiro.realm;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.Socket;
+import java.security.GeneralSecurityException;
+import java.security.SecureRandom;
+import java.security.cert.X509Certificate;
+
+import javax.net.SocketFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509TrustManager;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class SkipSSLCheckSocketFactory extends SocketFactory {
+
+    private static final Logger log = LoggerFactory.getLogger(SkipSSLCheckSocketFactory.class);
+
+    private static SocketFactory skipSSLCheckFactory = null;
+
+    static {
+        final TrustManager[] noOpTrustManagers = new TrustManager[]{
+                new X509TrustManager() {
+                    public X509Certificate[] getAcceptedIssuers() { return null; }
+
+                    public void checkClientTrusted(X509Certificate[] c, String a) { }
+
+                    public void checkServerTrusted(X509Certificate[] c, String a) { }
+                }};
+
+        try {
+            final SSLContext context = SSLContext.getInstance("SSL");
+            context.init(null, noOpTrustManagers, new SecureRandom());
+            skipSSLCheckFactory = context.getSocketFactory();
+        } catch (GeneralSecurityException e) {
+            log.warn("SSL exception", e);
+        }
+    }
+
+    public static SocketFactory getDefault() {
+        return new SkipSSLCheckSocketFactory();
+    }
+
+    public Socket createSocket(final String arg0, final int arg1) throws IOException {
+        return skipSSLCheckFactory.createSocket(arg0, arg1);
+    }
+
+    public Socket createSocket(final InetAddress arg0, final int arg1) throws IOException {
+        return skipSSLCheckFactory.createSocket(arg0, arg1);
+    }
+
+    public Socket createSocket(final String arg0, final int arg1, final InetAddress arg2, final int arg3) throws IOException {
+        return skipSSLCheckFactory.createSocket(arg0, arg1, arg2, arg3);
+    }
+
+    public Socket createSocket(final InetAddress arg0, final int arg1, final InetAddress arg2, final int arg3) throws IOException {
+        return skipSSLCheckFactory.createSocket(arg0, arg1, arg2, arg3);
+    }
+}
diff --git a/util/src/main/resources/com/ning/billing/util/dao/NonEntitySqlDao.sql.stg b/util/src/main/resources/com/ning/billing/util/dao/NonEntitySqlDao.sql.stg
index 3e11edb..1969615 100644
--- a/util/src/main/resources/com/ning/billing/util/dao/NonEntitySqlDao.sql.stg
+++ b/util/src/main/resources/com/ning/billing/util/dao/NonEntitySqlDao.sql.stg
@@ -8,6 +8,14 @@ where id = :id
 ;
 >>
 
+getIdFromObject(tableName) ::= <<
+select
+  id
+from <tableName>
+where record_id = :recordId
+;
+>>
+
 getAccountRecordIdFromAccountHistory() ::= <<
 select
   target_record_id
diff --git a/util/src/main/resources/com/ning/billing/util/ddl.sql b/util/src/main/resources/com/ning/billing/util/ddl.sql
index d0b48cd..b586ec2 100644
--- a/util/src/main/resources/com/ning/billing/util/ddl.sql
+++ b/util/src/main/resources/com/ning/billing/util/ddl.sql
@@ -224,3 +224,13 @@ DROP TABLE IF EXISTS notifications;
       search_key2 int(11) unsigned default null,
       PRIMARY KEY(record_id)
   );
+
+create table sessions (
+  record_id int(11) unsigned not null auto_increment
+, start_timestamp datetime not null
+, last_access_time datetime default null
+, timeout int(11)
+, host varchar(100) default null
+, session_data mediumblob default null
+, primary key(record_id)
+);
\ No newline at end of file
diff --git a/util/src/main/resources/com/ning/billing/util/security/shiro/dao/JDBCSessionSqlDao.sql.stg b/util/src/main/resources/com/ning/billing/util/security/shiro/dao/JDBCSessionSqlDao.sql.stg
new file mode 100644
index 0000000..fe228d2
--- /dev/null
+++ b/util/src/main/resources/com/ning/billing/util/security/shiro/dao/JDBCSessionSqlDao.sql.stg
@@ -0,0 +1,51 @@
+group JDBCSessionSqlDao;
+
+read() ::= <<
+select
+  record_id
+, start_timestamp
+, last_access_time
+, timeout
+, host
+, session_data
+from sessions
+where record_id = :recordId
+;
+>>
+
+create() ::= <<
+insert into sessions (
+  start_timestamp
+, last_access_time
+, timeout
+, host
+, session_data
+) values (
+  :startTimestamp
+, :lastAccessTime
+, :timeout
+, :host
+, :sessionData
+);
+>>
+
+update() ::= <<
+update sessions set
+  start_timestamp = :startTimestamp
+, last_access_time = :lastAccessTime
+, timeout = :timeout
+, host = :host
+, session_data = :sessionData
+where record_id = :recordId
+;
+>>
+
+delete() ::= <<
+delete from sessions
+where record_id = :recordId
+;
+>>
+
+getLastInsertId() ::= <<
+select LAST_INSERT_ID();
+>>
diff --git a/util/src/test/java/com/ning/billing/dao/MockNonEntityDao.java b/util/src/test/java/com/ning/billing/dao/MockNonEntityDao.java
index 4444bdf..3bb80f9 100644
--- a/util/src/test/java/com/ning/billing/dao/MockNonEntityDao.java
+++ b/util/src/test/java/com/ning/billing/dao/MockNonEntityDao.java
@@ -52,4 +52,9 @@ public class MockNonEntityDao implements NonEntityDao {
     public Long retrieveHistoryTargetRecordId(final Long recordId, final TableName tableName) {
         return null;
     }
+
+    @Override
+    public UUID retrieveIdFromObject(final Long recordId, final ObjectType objectType) {
+        return null;
+    }
 }
diff --git a/util/src/test/java/com/ning/billing/dbi/DBIProvider.java b/util/src/test/java/com/ning/billing/dbi/DBIProvider.java
index a54ee30..824e50e 100644
--- a/util/src/test/java/com/ning/billing/dbi/DBIProvider.java
+++ b/util/src/test/java/com/ning/billing/dbi/DBIProvider.java
@@ -16,8 +16,6 @@
 
 package com.ning.billing.dbi;
 
-import java.util.concurrent.TimeUnit;
-
 import javax.sql.DataSource;
 
 import org.skife.jdbi.v2.DBI;
@@ -39,24 +37,15 @@ import com.mchange.v2.c3p0.ComboPooledDataSource;
 
 public class DBIProvider implements Provider<IDBI> {
 
-    private final String jdbcUri;
-    private final String userName;
-    private final String userPwd;
+    private final DataSource ds;
 
     @Inject
-    public DBIProvider(final DbiConfig config) {
-        this(config.getJdbcUrl(), config.getUsername(), config.getPassword());
-    }
-
-    public DBIProvider(final String jdbcUri, final String userName, final String userPwd) {
-        this.jdbcUri = jdbcUri;
-        this.userName = userName;
-        this.userPwd = userPwd;
+    public DBIProvider(final DataSource ds) {
+        this.ds = ds;
     }
 
     @Override
     public IDBI get() {
-        final DataSource ds = getC3P0DataSource();
         final DBI dbi = new DBI(ds);
         dbi.registerArgumentFactory(new UUIDArgumentFactory());
         dbi.registerArgumentFactory(new DateTimeZoneArgumentFactory());
@@ -72,29 +61,4 @@ public class DBIProvider implements Provider<IDBI> {
 
         return dbi;
     }
-
-
-
-    private DataSource getBoneCPDatSource() {
-        final BoneCPConfig dbConfig = new BoneCPConfig();
-        dbConfig.setJdbcUrl(jdbcUri);
-        dbConfig.setUsername(userName);
-        dbConfig.setPassword(userPwd);
-        dbConfig.setPartitionCount(1);
-        //dbConfig.setDefaultTransactionIsolation("READ_COMMITTED");
-        dbConfig.setDisableJMX(false);
-
-        final BoneCPDataSource ds = new BoneCPDataSource(dbConfig);
-        return ds;
-    }
-
-    private DataSource getC3P0DataSource() {
-        ComboPooledDataSource cpds = new ComboPooledDataSource();
-        cpds.setJdbcUrl(jdbcUri);
-        cpds.setUser(userName);
-        cpds.setPassword(userPwd);
-        cpds.setMinPoolSize(1);
-        cpds.setMaxPoolSize(10);
-        return cpds;
-    }
 }
diff --git a/util/src/test/java/com/ning/billing/GuicyKillbillTestNoDBModule.java b/util/src/test/java/com/ning/billing/GuicyKillbillTestNoDBModule.java
index 265f94e..77adf8d 100644
--- a/util/src/test/java/com/ning/billing/GuicyKillbillTestNoDBModule.java
+++ b/util/src/test/java/com/ning/billing/GuicyKillbillTestNoDBModule.java
@@ -16,20 +16,11 @@
 
 package com.ning.billing;
 
-
 import org.mockito.Mockito;
 import org.skife.jdbi.v2.IDBI;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.ning.billing.dbi.DBTestingHelper;
-import com.ning.billing.dbi.H2TestingHelper;
-import com.ning.billing.dbi.MysqlTestingHelper;
 
 public class GuicyKillbillTestNoDBModule extends GuicyKillbillTestModule {
 
-    private final static Logger log = LoggerFactory.getLogger(GuicyKillbillTestNoDBModule.class);
-
     private void installDBI() {
         final IDBI idbi = Mockito.mock(IDBI.class);
         bind(IDBI.class).toInstance(idbi);
diff --git a/util/src/test/java/com/ning/billing/GuicyKillbillTestSuiteWithEmbeddedDB.java b/util/src/test/java/com/ning/billing/GuicyKillbillTestSuiteWithEmbeddedDB.java
index cfc6f22..1ac9403 100644
--- a/util/src/test/java/com/ning/billing/GuicyKillbillTestSuiteWithEmbeddedDB.java
+++ b/util/src/test/java/com/ning/billing/GuicyKillbillTestSuiteWithEmbeddedDB.java
@@ -17,6 +17,7 @@
 package com.ning.billing;
 
 import javax.inject.Inject;
+import javax.sql.DataSource;
 
 import org.skife.jdbi.v2.IDBI;
 import org.slf4j.Logger;
@@ -25,34 +26,30 @@ import org.testng.annotations.AfterSuite;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.BeforeSuite;
 
-import com.ning.billing.dbi.DBTestingHelper;
+import com.ning.billing.commons.embeddeddb.EmbeddedDB;
 
 public class GuicyKillbillTestSuiteWithEmbeddedDB extends GuicyKillbillTestSuite {
 
-    private static final Logger log = LoggerFactory.getLogger(KillbillTestSuiteWithEmbeddedDB.class);
+    private static final Logger log = LoggerFactory.getLogger(GuicyKillbillTestSuiteWithEmbeddedDB.class);
 
     @Inject
-    protected DBTestingHelper helper;
+    protected EmbeddedDB helper;
 
-    public DBTestingHelper getDBTestingHelper() {
-        return GuicyKillbillTestWithEmbeddedDBModule.getDBTestingHelper();
-    }
+    @Inject
+    protected DataSource dataSource;
 
-    public IDBI getDBI() {
-        return GuicyKillbillTestWithEmbeddedDBModule.getDBTestingHelper().getDBI();
-    }
+    @Inject
+    protected IDBI dbi;
 
     @BeforeSuite(groups = {"slow", "mysql"})
     public void beforeSuite() throws Exception {
-        GuicyKillbillTestWithEmbeddedDBModule.getDBTestingHelper().start();
-        GuicyKillbillTestWithEmbeddedDBModule.getDBTestingHelper().initDb();
-        GuicyKillbillTestWithEmbeddedDBModule.getDBTestingHelper().cleanupAllTables();
+        DBTestingHelper.start();
     }
 
     @BeforeMethod(groups = {"slow", "mysql"})
     public void beforeMethod() throws Exception {
         try {
-            GuicyKillbillTestWithEmbeddedDBModule.getDBTestingHelper().cleanupAllTables();
+            DBTestingHelper.get().cleanupAllTables();
         } catch (Exception ignored) {
         }
     }
@@ -62,13 +59,13 @@ public class GuicyKillbillTestSuiteWithEmbeddedDB extends GuicyKillbillTestSuite
         if (hasFailed()) {
             log.error("**********************************************************************************************");
             log.error("*** TESTS HAVE FAILED - LEAVING DB RUNNING FOR DEBUGGING - MAKE SURE TO KILL IT ONCE DONE ****");
-            log.error(GuicyKillbillTestWithEmbeddedDBModule.getDBTestingHelper().getConnectionString());
+            log.error(DBTestingHelper.get().getCmdLineConnectionString());
             log.error("**********************************************************************************************");
             return;
         }
 
         try {
-            GuicyKillbillTestWithEmbeddedDBModule.getDBTestingHelper().stop();
+            DBTestingHelper.get().stop();
         } catch (Exception ignored) {
         }
     }
diff --git a/util/src/test/java/com/ning/billing/GuicyKillbillTestWithEmbeddedDBModule.java b/util/src/test/java/com/ning/billing/GuicyKillbillTestWithEmbeddedDBModule.java
index c5567a1..43810bd 100644
--- a/util/src/test/java/com/ning/billing/GuicyKillbillTestWithEmbeddedDBModule.java
+++ b/util/src/test/java/com/ning/billing/GuicyKillbillTestWithEmbeddedDBModule.java
@@ -16,38 +16,29 @@
 
 package com.ning.billing;
 
+import java.io.IOException;
+
+import javax.sql.DataSource;
 
 import org.skife.jdbi.v2.IDBI;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import org.testng.Assert;
 
-import com.ning.billing.dbi.DBTestingHelper;
-import com.ning.billing.dbi.H2TestingHelper;
-import com.ning.billing.dbi.MysqlTestingHelper;
+import com.ning.billing.commons.embeddeddb.EmbeddedDB;
 
 public class GuicyKillbillTestWithEmbeddedDBModule extends GuicyKillbillTestModule {
 
-    private static final Logger log = LoggerFactory.getLogger(GuicyKillbillTestWithEmbeddedDBModule.class);
-
-    private static final DBTestingHelper instance = getDBTestingHelper();
-
-    public static synchronized DBTestingHelper getDBTestingHelper() {
-        if (instance == null) {
-            if ("true".equals(System.getProperty("com.ning.billing.dbi.test.h2"))) {
-                log.info("Using h2 as the embedded database");
-                return new H2TestingHelper();
-            } else {
-                log.info("Using MySQL as the embedded database");
-                return new MysqlTestingHelper();
-            }
-        }
-        return instance;
-    }
-
     @Override
     protected void configure() {
         super.configure();
-        bind(DBTestingHelper.class).toInstance(instance);
-        bind(IDBI.class).toInstance(instance.getDBI());
+
+        final EmbeddedDB instance = DBTestingHelper.get();
+        bind(EmbeddedDB.class).toInstance(instance);
+
+        try {
+            bind(DataSource.class).toInstance(DBTestingHelper.get().getDataSource());
+            bind(IDBI.class).toInstance(DBTestingHelper.getDBI());
+        } catch (IOException e) {
+            Assert.fail(e.toString());
+        }
     }
 }
diff --git a/util/src/test/java/com/ning/billing/KillbillTestSuiteWithEmbeddedDB.java b/util/src/test/java/com/ning/billing/KillbillTestSuiteWithEmbeddedDB.java
index 20d2451..0ac8b85 100644
--- a/util/src/test/java/com/ning/billing/KillbillTestSuiteWithEmbeddedDB.java
+++ b/util/src/test/java/com/ning/billing/KillbillTestSuiteWithEmbeddedDB.java
@@ -27,45 +27,19 @@ import org.testng.annotations.AfterSuite;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.BeforeSuite;
 
-import com.ning.billing.dbi.DBTestingHelper;
-import com.ning.billing.dbi.H2TestingHelper;
-import com.ning.billing.dbi.MysqlTestingHelper;
-
 public class KillbillTestSuiteWithEmbeddedDB extends KillbillTestSuite {
 
     private static final Logger log = LoggerFactory.getLogger(KillbillTestSuiteWithEmbeddedDB.class);
 
-    protected static DBTestingHelper helper;
-
-    static {
-        if ("true".equals(System.getProperty("com.ning.billing.dbi.test.h2"))) {
-            log.info("Using h2 as the embedded database");
-            helper = new H2TestingHelper();
-        } else {
-            log.info("Using MySQL as the embedded database");
-            helper = new MysqlTestingHelper();
-        }
-    }
-
-    public static DBTestingHelper getDBTestingHelper() {
-        return helper;
-    }
-
-    public static IDBI getDBI() {
-        return helper.getDBI();
-    }
-
     @BeforeSuite(groups = {"slow", "mysql"})
     public void startMysqlBeforeTestSuite() throws IOException, ClassNotFoundException, SQLException, URISyntaxException {
-        helper.start();
-        helper.initDb();
-        helper.cleanupAllTables();
+        DBTestingHelper.start();
     }
 
     @BeforeMethod(groups = {"slow", "mysql"})
     public void cleanupTablesBetweenMethods() {
         try {
-            helper.cleanupAllTables();
+            DBTestingHelper.get().cleanupAllTables();
         } catch (Exception ignored) {
         }
     }
@@ -75,13 +49,13 @@ public class KillbillTestSuiteWithEmbeddedDB extends KillbillTestSuite {
         if (hasFailed()) {
             log.error("**********************************************************************************************");
             log.error("*** TESTS HAVE FAILED - LEAVING DB RUNNING FOR DEBUGGING - MAKE SURE TO KILL IT ONCE DONE ****");
-            log.error(helper.getConnectionString());
+            log.error(DBTestingHelper.get().getCmdLineConnectionString());
             log.error("**********************************************************************************************");
             return;
         }
 
         try {
-            helper.stop();
+            DBTestingHelper.get().stop();
         } catch (Exception ignored) {
         }
     }
diff --git a/util/src/test/java/com/ning/billing/mock/api/MockAccountUserApi.java b/util/src/test/java/com/ning/billing/mock/api/MockAccountUserApi.java
index 16c758f..488b8d8 100644
--- a/util/src/test/java/com/ning/billing/mock/api/MockAccountUserApi.java
+++ b/util/src/test/java/com/ning/billing/mock/api/MockAccountUserApi.java
@@ -17,6 +17,7 @@
 package com.ning.billing.mock.api;
 
 import java.util.ArrayList;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.UUID;
 import java.util.concurrent.CopyOnWriteArrayList;
@@ -106,6 +107,20 @@ public class MockAccountUserApi implements AccountUserApi {
     }
 
     @Override
+    public List<Account> searchAccounts(final String searchKey, final TenantContext tenantContext) {
+        final List<Account> results = new LinkedList<Account>();
+        for (final Account account : accounts) {
+            if ((account.getName() != null && account.getName().contains(searchKey)) ||
+                (account.getEmail() != null && account.getEmail().contains(searchKey)) ||
+                (account.getExternalKey() != null && account.getExternalKey().contains(searchKey)) ||
+                (account.getCompanyName() != null && account.getCompanyName().contains(searchKey))) {
+                results.add(account);
+            }
+        }
+        return results;
+    }
+
+    @Override
     public List<Account> getAccounts(final TenantContext context) {
         return new ArrayList<Account>(accounts);
     }
diff --git a/util/src/test/java/com/ning/billing/mock/glue/MockGlobalLockerModule.java b/util/src/test/java/com/ning/billing/mock/glue/MockGlobalLockerModule.java
index 03fd184..5457791 100644
--- a/util/src/test/java/com/ning/billing/mock/glue/MockGlobalLockerModule.java
+++ b/util/src/test/java/com/ning/billing/mock/glue/MockGlobalLockerModule.java
@@ -16,8 +16,8 @@
 
 package com.ning.billing.mock.glue;
 
-import com.ning.billing.util.globallocker.GlobalLocker;
-import com.ning.billing.util.globallocker.MockGlobalLocker;
+import com.ning.billing.commons.locker.GlobalLocker;
+import com.ning.billing.commons.locker.memory.MemoryGlobalLocker;
 
 import com.google.inject.AbstractModule;
 
@@ -25,6 +25,6 @@ public class MockGlobalLockerModule extends AbstractModule {
 
     @Override
     protected void configure() {
-        bind(GlobalLocker.class).to(MockGlobalLocker.class).asEagerSingleton();
+        bind(GlobalLocker.class).to(MemoryGlobalLocker.class).asEagerSingleton();
     }
 }
diff --git a/util/src/test/java/com/ning/billing/payment/api/TestPaymentMethodPluginBase.java b/util/src/test/java/com/ning/billing/payment/api/TestPaymentMethodPluginBase.java
index 118303b..2737016 100644
--- a/util/src/test/java/com/ning/billing/payment/api/TestPaymentMethodPluginBase.java
+++ b/util/src/test/java/com/ning/billing/payment/api/TestPaymentMethodPluginBase.java
@@ -24,6 +24,11 @@ import com.google.common.collect.ImmutableList;
 public class TestPaymentMethodPluginBase implements PaymentMethodPlugin {
 
     @Override
+    public UUID getKbPaymentMethodId() {
+        return UUID.randomUUID();
+    }
+
+    @Override
     public String getExternalPaymentMethodId() {
         return UUID.randomUUID().toString();
     }
diff --git a/util/src/test/java/com/ning/billing/util/audit/dao/TestDefaultAuditDao.java b/util/src/test/java/com/ning/billing/util/audit/dao/TestDefaultAuditDao.java
index 6fbc2a9..bdee1c6 100644
--- a/util/src/test/java/com/ning/billing/util/audit/dao/TestDefaultAuditDao.java
+++ b/util/src/test/java/com/ning/billing/util/audit/dao/TestDefaultAuditDao.java
@@ -45,7 +45,7 @@ public class TestDefaultAuditDao extends UtilTestSuiteWithEmbeddedDB {
         addTag();
 
         // Verify we get an audit entry for the tag_history table
-        final Handle handle = getDBI().open();
+        final Handle handle = dbi.open();
         final String tagHistoryString = (String) handle.select("select id from tag_history limit 1").get(0).get("id");
         handle.close();
 
diff --git a/util/src/test/java/com/ning/billing/util/cache/TestCache.java b/util/src/test/java/com/ning/billing/util/cache/TestCache.java
index 07680f1..f1c4570 100644
--- a/util/src/test/java/com/ning/billing/util/cache/TestCache.java
+++ b/util/src/test/java/com/ning/billing/util/cache/TestCache.java
@@ -73,7 +73,7 @@ public class TestCache extends UtilTestSuiteWithEmbeddedDB {
     @Test(groups = "slow")
     public void testCacheRecordId() throws Exception {
 
-        this.transactionalSqlDao = new EntitySqlDaoTransactionalJdbiWrapper(getDBI(), clock, controlCacheDispatcher, nonEntityDao);
+        this.transactionalSqlDao = new EntitySqlDaoTransactionalJdbiWrapper(dbi, clock, controlCacheDispatcher, nonEntityDao);
         final TagModelDao tag = new TagModelDao(clock.getUTCNow(), UUID.randomUUID(), UUID.randomUUID(), ObjectType.TAG);
 
         // Verify we start with nothing in the cache
diff --git a/util/src/test/java/com/ning/billing/util/callcontext/TestInternalCallContextFactory.java b/util/src/test/java/com/ning/billing/util/callcontext/TestInternalCallContextFactory.java
index 0508da6..edfb7e8 100644
--- a/util/src/test/java/com/ning/billing/util/callcontext/TestInternalCallContextFactory.java
+++ b/util/src/test/java/com/ning/billing/util/callcontext/TestInternalCallContextFactory.java
@@ -40,7 +40,7 @@ public class TestInternalCallContextFactory extends UtilTestSuiteWithEmbeddedDB 
         final UUID invoiceId = UUID.randomUUID();
         final Long accountRecordId = 19384012L;
 
-        getDBI().withHandle(new HandleCallback<Void>() {
+        dbi.withHandle(new HandleCallback<Void>() {
             @Override
             public Void withHandle(final Handle handle) throws Exception {
                 handle.execute("DROP TABLE IF EXISTS invoices;\n" +
@@ -75,7 +75,7 @@ public class TestInternalCallContextFactory extends UtilTestSuiteWithEmbeddedDB 
         final UUID accountId = UUID.randomUUID();
         final Long accountRecordId = 19384012L;
 
-        getDBTestingHelper().getDBI().withHandle(new HandleCallback<Void>() {
+        dbi.withHandle(new HandleCallback<Void>() {
             @Override
             public Void withHandle(final Handle handle) throws Exception {
                 // Note: we always create an accounts table, see MysqlTestingHelper
diff --git a/util/src/test/java/com/ning/billing/util/customfield/api/TestDefaultCustomFieldUserApi.java b/util/src/test/java/com/ning/billing/util/customfield/api/TestDefaultCustomFieldUserApi.java
index ac85be2..6fe8609 100644
--- a/util/src/test/java/com/ning/billing/util/customfield/api/TestDefaultCustomFieldUserApi.java
+++ b/util/src/test/java/com/ning/billing/util/customfield/api/TestDefaultCustomFieldUserApi.java
@@ -41,7 +41,7 @@ public class TestDefaultCustomFieldUserApi extends UtilTestSuiteWithEmbeddedDB {
         final UUID accountId = UUID.randomUUID();
         final Long accountRecordId = 19384012L;
 
-        getDBI().withHandle(new HandleCallback<Void>() {
+        dbi.withHandle(new HandleCallback<Void>() {
             @Override
             public Void withHandle(final Handle handle) throws Exception {
                 // Note: we always create an accounts table, see MysqlTestingHelper
@@ -60,7 +60,7 @@ public class TestDefaultCustomFieldUserApi extends UtilTestSuiteWithEmbeddedDB {
         Assert.assertEquals(customFields.size(), 1);
         Assert.assertEquals(customFields.get(0), customField);
         // Verify the account_record_id was populated
-        getDBTestingHelper().getDBI().withHandle(new HandleCallback<Void>() {
+        dbi.withHandle(new HandleCallback<Void>() {
             @Override
             public Void withHandle(final Handle handle) throws Exception {
                 final List<Map<String, Object>> values = handle.select("select account_record_id from custom_fields where object_id = ?", accountId.toString());
diff --git a/util/src/test/java/com/ning/billing/util/dao/TestNonEntityDao.java b/util/src/test/java/com/ning/billing/util/dao/TestNonEntityDao.java
index 153968f..efbe509 100644
--- a/util/src/test/java/com/ning/billing/util/dao/TestNonEntityDao.java
+++ b/util/src/test/java/com/ning/billing/util/dao/TestNonEntityDao.java
@@ -16,6 +16,7 @@
 
 package com.ning.billing.util.dao;
 
+import java.io.IOException;
 import java.util.Date;
 import java.util.UUID;
 
@@ -47,8 +48,7 @@ public class TestNonEntityDao extends UtilTestSuiteWithEmbeddedDB {
 
 
     @Test(groups = "slow")
-    public void testRetrieveRecordIdFromObject() {
-
+    public void testRetrieveRecordIdFromObject() throws IOException {
         insertAccount();
 
         final Long resultRecordId = nonEntityDao.retrieveRecordIdFromObject(accountId, ObjectType.ACCOUNT, null);
@@ -56,8 +56,7 @@ public class TestNonEntityDao extends UtilTestSuiteWithEmbeddedDB {
     }
 
     @Test(groups = "slow")
-    public void testRetrieveAccountRecordIdFromAccountObject() {
-
+    public void testRetrieveAccountRecordIdFromAccountObject() throws IOException {
         insertAccount();
 
         final Long resultAccountRecordId = nonEntityDao.retrieveAccountRecordIdFromObject(accountId, ObjectType.ACCOUNT, null);
@@ -66,8 +65,7 @@ public class TestNonEntityDao extends UtilTestSuiteWithEmbeddedDB {
 
 
     @Test(groups = "slow")
-    public void testRetrieveAccountRecordIdFromTagDefinitionObject() {
-
+    public void testRetrieveAccountRecordIdFromTagDefinitionObject() throws IOException {
         insertTagDefinition();
 
         final Long resultAccountRecordId = nonEntityDao.retrieveAccountRecordIdFromObject(tagDefinitionId, ObjectType.TAG_DEFINITION, null);
@@ -76,8 +74,7 @@ public class TestNonEntityDao extends UtilTestSuiteWithEmbeddedDB {
 
     // Not Tag_definition or account which are special
     @Test(groups = "slow")
-    public void testRetrieveAccountRecordIdFromOtherObject() {
-
+    public void testRetrieveAccountRecordIdFromOtherObject() throws IOException {
         insertTag();
 
         final Long resultAccountRecordId = nonEntityDao.retrieveAccountRecordIdFromObject(tagId, ObjectType.TAG, null);
@@ -85,8 +82,7 @@ public class TestNonEntityDao extends UtilTestSuiteWithEmbeddedDB {
     }
 
     @Test(groups = "slow")
-    public void testRetrieveTenantRecordIdFromObject() {
-
+    public void testRetrieveTenantRecordIdFromObject() throws IOException {
         insertAccount();
 
         final Long resultTenantRecordId = nonEntityDao.retrieveTenantRecordIdFromObject(accountId, ObjectType.ACCOUNT, null);
@@ -94,15 +90,14 @@ public class TestNonEntityDao extends UtilTestSuiteWithEmbeddedDB {
     }
 
     @Test(groups = "slow")
-    public void testRetrieveTenantRecordIdFromTenantObject() {
-
+    public void testRetrieveTenantRecordIdFromTenantObject() throws IOException {
         insertTenant();
 
         final Long resultTenantRecordId = nonEntityDao.retrieveTenantRecordIdFromObject(tenantId, ObjectType.TENANT, null);
         Assert.assertEquals(resultTenantRecordId, tenantRecordId);
     }
-    private void insertAccount() {
-        getDBI().withHandle(new HandleCallback<Void>() {
+    private void insertAccount() throws IOException {
+        dbi.withHandle(new HandleCallback<Void>() {
             @Override
             public Void withHandle(final Handle handle) throws Exception {
                 // Note: we always create an accounts table, see MysqlTestingHelper
@@ -113,8 +108,8 @@ public class TestNonEntityDao extends UtilTestSuiteWithEmbeddedDB {
         });
     }
 
-    private void insertHistoryAccount() {
-        getDBI().withHandle(new HandleCallback<Void>() {
+    private void insertHistoryAccount() throws IOException {
+        dbi.withHandle(new HandleCallback<Void>() {
             @Override
             public Void withHandle(final Handle handle) throws Exception {
                 // Note: we always create an accounts table, see MysqlTestingHelper
@@ -126,8 +121,8 @@ public class TestNonEntityDao extends UtilTestSuiteWithEmbeddedDB {
     }
 
 
-    private void insertTagDefinition() {
-        getDBI().withHandle(new HandleCallback<Void>() {
+    private void insertTagDefinition() throws IOException {
+        dbi.withHandle(new HandleCallback<Void>() {
             @Override
             public Void withHandle(final Handle handle) throws Exception {
                 // Note: we always create an accounts table, see MysqlTestingHelper
@@ -138,8 +133,8 @@ public class TestNonEntityDao extends UtilTestSuiteWithEmbeddedDB {
         });
     }
 
-    private void insertTag() {
-        getDBI().withHandle(new HandleCallback<Void>() {
+    private void insertTag() throws IOException {
+        dbi.withHandle(new HandleCallback<Void>() {
             @Override
             public Void withHandle(final Handle handle) throws Exception {
                 // Note: we always create an accounts table, see MysqlTestingHelper
@@ -150,8 +145,8 @@ public class TestNonEntityDao extends UtilTestSuiteWithEmbeddedDB {
         });
     }
 
-    private void insertTenant() {
-        getDBI().withHandle(new HandleCallback<Void>() {
+    private void insertTenant() throws IOException {
+        dbi.withHandle(new HandleCallback<Void>() {
             @Override
             public Void withHandle(final Handle handle) throws Exception {
                 // Note: we always create an accounts table, see MysqlTestingHelper
diff --git a/util/src/test/java/com/ning/billing/util/dao/TestStringTemplateInheritanceWithJdbi.java b/util/src/test/java/com/ning/billing/util/dao/TestStringTemplateInheritanceWithJdbi.java
index ef86f5b..24abcd5 100644
--- a/util/src/test/java/com/ning/billing/util/dao/TestStringTemplateInheritanceWithJdbi.java
+++ b/util/src/test/java/com/ning/billing/util/dao/TestStringTemplateInheritanceWithJdbi.java
@@ -42,7 +42,7 @@ public class TestStringTemplateInheritanceWithJdbi extends UtilTestSuiteWithEmbe
 
     @Test(groups = "slow")
     public void testInheritQueries() throws Exception {
-        final KombuchaSqlDao dao = getDBI().onDemand(KombuchaSqlDao.class);
+        final KombuchaSqlDao dao = dbi.onDemand(KombuchaSqlDao.class);
 
         // Verify non inherited template
         Assert.assertEquals(dao.isIsTimeForKombucha(), clock.getUTCNow().getHourOfDay() == 17);
diff --git a/util/src/test/java/com/ning/billing/util/export/dao/TestDatabaseExportDao.java b/util/src/test/java/com/ning/billing/util/export/dao/TestDatabaseExportDao.java
index 9e2184b..17739b1 100644
--- a/util/src/test/java/com/ning/billing/util/export/dao/TestDatabaseExportDao.java
+++ b/util/src/test/java/com/ning/billing/util/export/dao/TestDatabaseExportDao.java
@@ -50,7 +50,7 @@ public class TestDatabaseExportDao extends UtilTestSuiteWithEmbeddedDB {
 
         final String tableNameA = "test_database_export_dao_a";
         final String tableNameB = "test_database_export_dao_b";
-        getDBTestingHelper().getDBI().withHandle(new HandleCallback<Void>() {
+        dbi.withHandle(new HandleCallback<Void>() {
             @Override
             public Void withHandle(final Handle handle) throws Exception {
                 handle.execute("drop table if exists " + tableNameA);
diff --git a/util/src/test/java/com/ning/billing/util/globallocker/TestGlobalLockerModule.java b/util/src/test/java/com/ning/billing/util/globallocker/TestGlobalLockerModule.java
index 5b0acad..06bdd94 100644
--- a/util/src/test/java/com/ning/billing/util/globallocker/TestGlobalLockerModule.java
+++ b/util/src/test/java/com/ning/billing/util/globallocker/TestGlobalLockerModule.java
@@ -16,8 +16,7 @@
 
 package com.ning.billing.util.globallocker;
 
-import com.ning.billing.dbi.DBTestingHelper;
-import com.ning.billing.dbi.DBTestingHelper.DBEngine;
+import com.ning.billing.commons.embeddeddb.EmbeddedDB;
 import com.ning.billing.mock.glue.MockGlobalLockerModule;
 import com.ning.billing.util.glue.GlobalLockerModule;
 
@@ -25,15 +24,15 @@ import com.google.inject.AbstractModule;
 
 public class TestGlobalLockerModule extends AbstractModule {
 
-    private final DBTestingHelper helper;
+    private final EmbeddedDB helper;
 
-    public TestGlobalLockerModule(final DBTestingHelper helper) {
+    public TestGlobalLockerModule(final EmbeddedDB helper) {
         this.helper = helper;
     }
 
     @Override
     protected void configure() {
-        if (DBEngine.MYSQL.equals(helper.getDBEngine())) {
+        if (EmbeddedDB.DBEngine.MYSQL.equals(helper.getDBEngine())) {
             install(new GlobalLockerModule());
         } else {
             install(new MockGlobalLockerModule());
diff --git a/util/src/test/java/com/ning/billing/util/globallocker/TestMysqlGlobalLocker.java b/util/src/test/java/com/ning/billing/util/globallocker/TestMysqlGlobalLocker.java
index 8682bc5..f6d695a 100644
--- a/util/src/test/java/com/ning/billing/util/globallocker/TestMysqlGlobalLocker.java
+++ b/util/src/test/java/com/ning/billing/util/globallocker/TestMysqlGlobalLocker.java
@@ -16,6 +16,7 @@
 
 package com.ning.billing.util.globallocker;
 
+import java.io.IOException;
 import java.util.UUID;
 
 import org.skife.jdbi.v2.Handle;
@@ -24,21 +25,23 @@ import org.skife.jdbi.v2.TransactionStatus;
 import org.testng.Assert;
 import org.testng.annotations.Test;
 
+import com.ning.billing.commons.locker.GlobalLock;
+import com.ning.billing.commons.locker.GlobalLocker;
+import com.ning.billing.commons.locker.LockFailedException;
+import com.ning.billing.commons.locker.mysql.MySqlGlobalLocker;
 import com.ning.billing.util.UtilTestSuiteWithEmbeddedDB;
-import com.ning.billing.util.globallocker.GlobalLocker.LockerType;
 
 public class TestMysqlGlobalLocker extends UtilTestSuiteWithEmbeddedDB {
 
-
     // Used as a manual test to validate the simple DAO by stepping through that locking is done and release correctly
     @Test(groups = "mysql")
-    public void testSimpleLocking() {
+    public void testSimpleLocking() throws IOException, LockFailedException {
         final String lockName = UUID.randomUUID().toString();
 
-        final GlobalLocker locker = new MySqlGlobalLocker(getDBI());
-        final GlobalLock lock = locker.lockWithNumberOfTries(LockerType.ACCOUNT_FOR_INVOICE_PAYMENTS, lockName, 3);
+        final GlobalLocker locker = new MySqlGlobalLocker(dataSource);
+        final GlobalLock lock = locker.lockWithNumberOfTries(LockerType.ACCOUNT_FOR_INVOICE_PAYMENTS.toString(), lockName, 3);
 
-        getDBI().inTransaction(new TransactionCallback<Void>() {
+        dbi.inTransaction(new TransactionCallback<Void>() {
             @Override
             public Void inTransaction(final Handle conn, final TransactionStatus status)
                     throws Exception {
@@ -46,11 +49,11 @@ public class TestMysqlGlobalLocker extends UtilTestSuiteWithEmbeddedDB {
                 return null;
             }
         });
-        Assert.assertEquals(locker.isFree(LockerType.ACCOUNT_FOR_INVOICE_PAYMENTS, lockName), Boolean.FALSE);
+        Assert.assertEquals(locker.isFree(LockerType.ACCOUNT_FOR_INVOICE_PAYMENTS.toString(), lockName), false);
 
         boolean gotException = false;
         try {
-            locker.lockWithNumberOfTries(LockerType.ACCOUNT_FOR_INVOICE_PAYMENTS, lockName, 1);
+            locker.lockWithNumberOfTries(LockerType.ACCOUNT_FOR_INVOICE_PAYMENTS.toString(), lockName, 1);
         } catch (LockFailedException e) {
             gotException = true;
         }
@@ -58,6 +61,6 @@ public class TestMysqlGlobalLocker extends UtilTestSuiteWithEmbeddedDB {
 
         lock.release();
 
-        Assert.assertEquals(locker.isFree(LockerType.ACCOUNT_FOR_INVOICE_PAYMENTS, lockName), Boolean.TRUE);
+        Assert.assertEquals(locker.isFree(LockerType.ACCOUNT_FOR_INVOICE_PAYMENTS.toString(), lockName), true);
     }
 }
diff --git a/util/src/test/java/com/ning/billing/util/glue/TestUtilModuleNoDB.java b/util/src/test/java/com/ning/billing/util/glue/TestUtilModuleNoDB.java
index ec302c8..a5b8594 100644
--- a/util/src/test/java/com/ning/billing/util/glue/TestUtilModuleNoDB.java
+++ b/util/src/test/java/com/ning/billing/util/glue/TestUtilModuleNoDB.java
@@ -50,5 +50,9 @@ public class TestUtilModuleNoDB extends TestUtilModule {
         install(new MockNotificationQueueModule(configSource));
 
         installAuditMock();
+
+        install(new KillBillShiroModule());
+        install(new KillBillShiroAopModule());
+        install(new SecurityModule());
     }
 }
diff --git a/util/src/test/java/com/ning/billing/util/security/api/TestDefaultSecurityApi.java b/util/src/test/java/com/ning/billing/util/security/api/TestDefaultSecurityApi.java
new file mode 100644
index 0000000..e76f64b
--- /dev/null
+++ b/util/src/test/java/com/ning/billing/util/security/api/TestDefaultSecurityApi.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2010-2013 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.security.api;
+
+import java.util.Set;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.ning.billing.security.Permission;
+import com.ning.billing.security.api.SecurityApi;
+import com.ning.billing.util.UtilTestSuiteNoDB;
+
+import com.google.common.collect.ImmutableList;
+
+public class TestDefaultSecurityApi extends UtilTestSuiteNoDB {
+
+    @Test(groups = "fast")
+    public void testRetrievePermissions() throws Exception {
+        configureShiro();
+
+        // We don't want the Guice injected one (it has Shiro disabled)
+        final SecurityApi securityApi = new DefaultSecurityApi();
+
+        final Set<Permission> anonsPermissions = securityApi.getCurrentUserPermissions(callContext);
+        Assert.assertEquals(anonsPermissions.size(), 0);
+
+        login("pierre");
+        final Set<Permission> pierresPermissions = securityApi.getCurrentUserPermissions(callContext);
+        Assert.assertEquals(pierresPermissions.size(), 2);
+        Assert.assertTrue(pierresPermissions.containsAll(ImmutableList.<Permission>of(Permission.INVOICE_CAN_CREDIT, Permission.INVOICE_CAN_ITEM_ADJUST)));
+
+        login("stephane");
+        final Set<Permission> stephanesPermissions = securityApi.getCurrentUserPermissions(callContext);
+        Assert.assertEquals(stephanesPermissions.size(), 1);
+        Assert.assertTrue(stephanesPermissions.containsAll(ImmutableList.<Permission>of(Permission.PAYMENT_CAN_REFUND)));
+    }
+}
diff --git a/util/src/test/java/com/ning/billing/util/security/shiro/dao/TestJDBCSessionDao.java b/util/src/test/java/com/ning/billing/util/security/shiro/dao/TestJDBCSessionDao.java
new file mode 100644
index 0000000..1b13ce7
--- /dev/null
+++ b/util/src/test/java/com/ning/billing/util/security/shiro/dao/TestJDBCSessionDao.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2010-2013 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.security.shiro.dao;
+
+import java.io.Serializable;
+import java.util.Date;
+import java.util.UUID;
+
+import org.apache.shiro.session.Session;
+import org.apache.shiro.session.mgt.SimpleSession;
+import org.skife.jdbi.v2.DBI;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.ning.billing.util.UtilTestSuiteWithEmbeddedDB;
+
+public class TestJDBCSessionDao extends UtilTestSuiteWithEmbeddedDB {
+
+    @Test(groups = "slow")
+    public void testCRUD() throws Exception {
+        // Note! We are testing the do* methods here to bypass the caching layer
+        final JDBCSessionDao jdbcSessionDao = new JDBCSessionDao((DBI) dbi);
+
+        // Retrieve
+        final SimpleSession session = createSession();
+        Assert.assertNull(jdbcSessionDao.doReadSession(session.getId()));
+
+        // Create
+        final Serializable sessionId = jdbcSessionDao.doCreate(session);
+        final Session retrievedSession = jdbcSessionDao.doReadSession(sessionId);
+        Assert.assertEquals(retrievedSession, session);
+
+        // Update
+        final String newHost = UUID.randomUUID().toString();
+        Assert.assertNotEquals(retrievedSession.getHost(), newHost);
+        session.setHost(newHost);
+        jdbcSessionDao.doUpdate(session);
+        Assert.assertEquals(jdbcSessionDao.doReadSession(sessionId).getHost(), newHost);
+
+        // Delete
+        jdbcSessionDao.doDelete(session);
+        Assert.assertNull(jdbcSessionDao.doReadSession(session.getId()));
+    }
+
+    private SimpleSession createSession() {
+        final SimpleSession simpleSession = new SimpleSession();
+        simpleSession.setStartTimestamp(new Date(System.currentTimeMillis() - 5000));
+        simpleSession.setLastAccessTime(new Date(System.currentTimeMillis()));
+        simpleSession.setTimeout(493934L);
+        simpleSession.setHost(UUID.randomUUID().toString());
+        simpleSession.setAttribute(UUID.randomUUID().toString(), Short.MIN_VALUE);
+        simpleSession.setAttribute(UUID.randomUUID().toString(), Integer.MIN_VALUE);
+        simpleSession.setAttribute(UUID.randomUUID().toString(), Long.MIN_VALUE);
+        simpleSession.setAttribute(UUID.randomUUID().toString(), UUID.randomUUID().toString());
+        // Test with Serializable objects
+        simpleSession.setAttribute(UUID.randomUUID().toString(), UUID.randomUUID());
+        simpleSession.setAttribute(UUID.randomUUID().toString(), new Date(1242));
+        return simpleSession;
+    }
+}
diff --git a/util/src/test/java/com/ning/billing/util/security/shiro/dao/TestSessionModelDao.java b/util/src/test/java/com/ning/billing/util/security/shiro/dao/TestSessionModelDao.java
new file mode 100644
index 0000000..bf14642
--- /dev/null
+++ b/util/src/test/java/com/ning/billing/util/security/shiro/dao/TestSessionModelDao.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2010-2013 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.security.shiro.dao;
+
+import java.util.Date;
+import java.util.UUID;
+
+import org.apache.shiro.session.Session;
+import org.apache.shiro.session.mgt.SimpleSession;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.ning.billing.util.UtilTestSuiteNoDB;
+
+public class TestSessionModelDao extends UtilTestSuiteNoDB {
+
+    @Test(groups = "fast")
+    public void testRoundTrip() throws Exception {
+        final SimpleSession simpleSession = new SimpleSession();
+        simpleSession.setStartTimestamp(new Date(System.currentTimeMillis() - 5000));
+        simpleSession.setLastAccessTime(new Date(System.currentTimeMillis()));
+        simpleSession.setTimeout(493934L);
+        simpleSession.setHost(UUID.randomUUID().toString());
+        simpleSession.setAttribute(UUID.randomUUID(), Short.MIN_VALUE);
+        simpleSession.setAttribute(UUID.randomUUID(), Integer.MIN_VALUE);
+        simpleSession.setAttribute(UUID.randomUUID(), Long.MIN_VALUE);
+        simpleSession.setAttribute(UUID.randomUUID().toString(), UUID.randomUUID().toString());
+        // Test with Serializable objects
+        simpleSession.setAttribute(UUID.randomUUID().toString(), UUID.randomUUID());
+        simpleSession.setAttribute(UUID.randomUUID().toString(), new Date(1242));
+
+        final SessionModelDao sessionModelDao = new SessionModelDao(simpleSession);
+        Assert.assertEquals(sessionModelDao.getTimeout(), simpleSession.getTimeout());
+        Assert.assertEquals(sessionModelDao.getHost(), simpleSession.getHost());
+        Assert.assertTrue(sessionModelDao.getSessionData().length > 0);
+
+        final Session retrievedSession = sessionModelDao.toSimpleSession();
+        Assert.assertEquals(retrievedSession, simpleSession);
+    }
+}
diff --git a/util/src/test/java/com/ning/billing/util/security/shiro/realm/TestKillBillJndiLdapRealm.java b/util/src/test/java/com/ning/billing/util/security/shiro/realm/TestKillBillJndiLdapRealm.java
new file mode 100644
index 0000000..8b4d8d2
--- /dev/null
+++ b/util/src/test/java/com/ning/billing/util/security/shiro/realm/TestKillBillJndiLdapRealm.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2010-2013 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.security.shiro.realm;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.Properties;
+
+import org.apache.shiro.authc.AuthenticationInfo;
+import org.apache.shiro.authc.UsernamePasswordToken;
+import org.apache.shiro.authz.AuthorizationInfo;
+import org.apache.shiro.subject.SimplePrincipalCollection;
+import org.skife.config.ConfigSource;
+import org.skife.config.ConfigurationObjectFactory;
+import org.skife.config.SimplePropertyConfigSource;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.ning.billing.util.UtilTestSuiteNoDB;
+import com.ning.billing.util.config.SecurityConfig;
+
+import com.google.common.collect.Sets;
+
+public class TestKillBillJndiLdapRealm extends UtilTestSuiteNoDB {
+
+    @Test(groups = "fast")
+    public void testCheckConfiguration() throws Exception {
+        // Test default configuration (see SecurityConfig)
+        final Map<String, Collection<String>> permission = killBillJndiLdapRealm.getPermissionsByGroup();
+
+        Assert.assertEquals(permission.get("admin").size(), 1);
+        Assert.assertEquals(permission.get("admin").iterator().next(), "*:*");
+
+        Assert.assertEquals(permission.get("finance").size(), 2);
+        Assert.assertEquals(Sets.newHashSet(permission.get("finance")), Sets.newHashSet("invoice:*", "payment:*"));
+
+        Assert.assertEquals(permission.get("support").size(), 2);
+        Assert.assertEquals(Sets.newHashSet(permission.get("support")), Sets.newHashSet("entitlement:*", "invoice:item_adjust"));
+    }
+
+    @Test(groups = "external", enabled = false)
+    public void testCheckLDAPConnection() throws Exception {
+        // Convenience method to verify your LDAP connectivity
+        final Properties props = new Properties();
+        props.setProperty("killbill.security.ldap.userDnTemplate", "uid={0},ou=users,dc=mycompany,dc=com");
+        props.setProperty("killbill.security.ldap.searchBase", "ou=groups,dc=mycompany,dc=com");
+        props.setProperty("killbill.security.ldap.groupSearchFilter", "memberOf=uid={0},ou=users,dc=mycompany,dc=com");
+        props.setProperty("killbill.security.ldap.groupNameId", "cn");
+        props.setProperty("killbill.security.ldap.url", "ldap://ldap:389");
+        props.setProperty("killbill.security.ldap.disableSSLCheck", "true");
+        props.setProperty("killbill.security.ldap.systemUsername", "cn=root");
+        props.setProperty("killbill.security.ldap.systemPassword", "password");
+        props.setProperty("killbill.security.ldap.authenticationMechanism", "simple");
+        props.setProperty("killbill.security.ldap.permissionsByGroup", "support-group: entitlement:*\n" +
+                                                                       "finance-group: invoice:*, payment:*\n" +
+                                                                       "ops-group: *:*");
+        final ConfigSource customConfigSource = new SimplePropertyConfigSource(props);
+        final SecurityConfig securityConfig = new ConfigurationObjectFactory(customConfigSource).build(SecurityConfig.class);
+        final KillBillJndiLdapRealm ldapRealm = new KillBillJndiLdapRealm(securityConfig);
+
+        final String username = "pierre";
+        final String password = "password";
+
+        // Check authentication
+        final UsernamePasswordToken token = new UsernamePasswordToken(username, password);
+        final AuthenticationInfo authenticationInfo = ldapRealm.getAuthenticationInfo(token);
+        System.out.println(authenticationInfo);
+
+        // Check permissions
+        final SimplePrincipalCollection principals = new SimplePrincipalCollection(username, username);
+        final AuthorizationInfo authorizationInfo = ldapRealm.queryForAuthorizationInfo(principals, ldapRealm.getContextFactory());
+        System.out.println("Roles: " + authorizationInfo.getRoles());
+        System.out.println("Permissions: " + authorizationInfo.getStringPermissions());
+    }
+}
diff --git a/util/src/test/java/com/ning/billing/util/security/TestPermissionAnnotationMethodInterceptor.java b/util/src/test/java/com/ning/billing/util/security/TestPermissionAnnotationMethodInterceptor.java
new file mode 100644
index 0000000..2330078
--- /dev/null
+++ b/util/src/test/java/com/ning/billing/util/security/TestPermissionAnnotationMethodInterceptor.java
@@ -0,0 +1,146 @@
+/*
+ * Copyright 2010-2013 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.security;
+
+import javax.inject.Singleton;
+
+import org.apache.shiro.authz.AuthorizationException;
+import org.apache.shiro.authz.UnauthenticatedException;
+import org.mockito.Mockito;
+import org.skife.jdbi.v2.IDBI;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.ning.billing.security.Permission;
+import com.ning.billing.security.RequiresPermissions;
+import com.ning.billing.util.UtilTestSuiteNoDB;
+import com.ning.billing.util.glue.KillBillShiroAopModule;
+import com.ning.billing.util.glue.KillBillShiroModule;
+import com.ning.billing.util.glue.SecurityModule;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.Stage;
+import net.sf.ehcache.CacheManager;
+
+public class TestPermissionAnnotationMethodInterceptor extends UtilTestSuiteNoDB {
+
+    public static interface IAopTester {
+
+        @RequiresPermissions(Permission.PAYMENT_CAN_REFUND)
+        public void createRefund();
+    }
+
+    public static class AopTesterImpl implements IAopTester {
+
+        @Override
+        public void createRefund() {}
+    }
+
+    @Singleton
+    public static class AopTester implements IAopTester {
+
+        @RequiresPermissions(Permission.PAYMENT_CAN_REFUND)
+        public void createRefund() {}
+    }
+
+    @Test(groups = "fast")
+    public void testAOPForClass() throws Exception {
+        // Make sure it works as expected without any AOP magic
+        final IAopTester simpleTester = new AopTester();
+        try {
+            simpleTester.createRefund();
+        } catch (Exception e) {
+            Assert.fail(e.getLocalizedMessage());
+        }
+
+        // Now, verify the interception works
+        configureShiro();
+        // Shutdown the cache manager to avoid duplicate exceptions
+        CacheManager.getInstance().shutdown();
+        final Injector injector = Guice.createInjector(Stage.PRODUCTION,
+                                                       new KillBillShiroModule(),
+                                                       new KillBillShiroAopModule(),
+                                                       new SecurityModule(),
+                                                       new AbstractModule() {
+                                                           @Override
+                                                           protected void configure() {
+                                                               bind(IDBI.class).toInstance(Mockito.mock(IDBI.class));
+                                                           }
+                                                       });
+        final AopTester aopedTester = injector.getInstance(AopTester.class);
+        verifyAopedTester(aopedTester);
+    }
+
+    @Test(groups = "fast")
+    public void testAOPForInterface() throws Exception {
+        // Make sure it works as expected without any AOP magic
+        final IAopTester simpleTester = new AopTesterImpl();
+        try {
+            simpleTester.createRefund();
+        } catch (Exception e) {
+            Assert.fail(e.getLocalizedMessage());
+        }
+
+        // Now, verify the interception works
+        configureShiro();
+        // Shutdown the cache manager to avoid duplicate exceptions
+        CacheManager.getInstance().shutdown();
+        final Injector injector = Guice.createInjector(Stage.PRODUCTION,
+                                                       new KillBillShiroModule(),
+                                                       new KillBillShiroAopModule(),
+                                                       new SecurityModule(),
+                                                       new AbstractModule() {
+                                                           @Override
+                                                           public void configure() {
+                                                               bind(IDBI.class).toInstance(Mockito.mock(IDBI.class));
+                                                               bind(IAopTester.class).to(AopTesterImpl.class).asEagerSingleton();
+                                                           }
+                                                       });
+        final IAopTester aopedTester = injector.getInstance(IAopTester.class);
+        verifyAopedTester(aopedTester);
+    }
+
+    private void verifyAopedTester(final IAopTester aopedTester) {
+        // Anonymous user
+        logout();
+        try {
+            aopedTester.createRefund();
+            Assert.fail();
+        } catch (UnauthenticatedException e) {
+            // Good!
+        } catch (Exception e) {
+            Assert.fail(e.getLocalizedMessage());
+        }
+
+        // pierre can credit, but not refund
+        login("pierre");
+        try {
+            aopedTester.createRefund();
+            Assert.fail();
+        } catch (AuthorizationException e) {
+            // Good!
+        } catch (Exception e) {
+            Assert.fail(e.getLocalizedMessage());
+        }
+
+        // stephane can refund
+        login("stephane");
+        aopedTester.createRefund();
+    }
+}
diff --git a/util/src/test/java/com/ning/billing/util/UtilTestSuiteNoDB.java b/util/src/test/java/com/ning/billing/util/UtilTestSuiteNoDB.java
index f82fc0d..acb66b1 100644
--- a/util/src/test/java/com/ning/billing/util/UtilTestSuiteNoDB.java
+++ b/util/src/test/java/com/ning/billing/util/UtilTestSuiteNoDB.java
@@ -18,18 +18,30 @@ package com.ning.billing.util;
 
 import javax.inject.Inject;
 
+import org.apache.shiro.SecurityUtils;
+import org.apache.shiro.authc.AuthenticationToken;
+import org.apache.shiro.authc.UsernamePasswordToken;
+import org.apache.shiro.config.Ini;
+import org.apache.shiro.config.IniSecurityManagerFactory;
+import org.apache.shiro.mgt.SecurityManager;
+import org.apache.shiro.subject.Subject;
+import org.apache.shiro.util.Factory;
+import org.apache.shiro.util.ThreadContext;
 import org.testng.annotations.AfterMethod;
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.BeforeMethod;
 
 import com.ning.billing.GuicyKillbillTestSuiteNoDB;
 import com.ning.billing.bus.api.PersistentBus;
+import com.ning.billing.security.Permission;
+import com.ning.billing.security.api.SecurityApi;
 import com.ning.billing.util.api.AuditUserApi;
 import com.ning.billing.util.audit.dao.AuditDao;
 import com.ning.billing.util.cache.CacheControllerDispatcher;
 import com.ning.billing.util.callcontext.InternalCallContextFactory;
 import com.ning.billing.util.dao.NonEntityDao;
 import com.ning.billing.util.glue.TestUtilModuleNoDB;
+import com.ning.billing.util.security.shiro.realm.KillBillJndiLdapRealm;
 
 import com.google.inject.Guice;
 import com.google.inject.Injector;
@@ -37,7 +49,6 @@ import com.google.inject.Stage;
 
 public class UtilTestSuiteNoDB extends GuicyKillbillTestSuiteNoDB {
 
-
     @Inject
     protected PersistentBus eventBus;
     @Inject
@@ -52,6 +63,10 @@ public class UtilTestSuiteNoDB extends GuicyKillbillTestSuiteNoDB {
     protected AuditDao auditDao;
     @Inject
     protected AuditUserApi auditUserApi;
+    @Inject
+    protected SecurityApi securityApi;
+    @Inject
+    protected KillBillJndiLdapRealm killBillJndiLdapRealm;
 
     @BeforeClass(groups = "fast")
     public void beforeClass() throws Exception {
@@ -69,4 +84,37 @@ public class UtilTestSuiteNoDB extends GuicyKillbillTestSuiteNoDB {
         eventBus.stop();
     }
 
+    // Security helpers
+
+    protected void login(final String username) {
+        logout();
+
+        final AuthenticationToken token = new UsernamePasswordToken(username, "password");
+        final Subject currentUser = SecurityUtils.getSubject();
+        currentUser.login(token);
+    }
+
+    protected void logout() {
+        final Subject currentUser = SecurityUtils.getSubject();
+        if (currentUser.isAuthenticated()) {
+            currentUser.logout();
+        }
+    }
+
+    protected void configureShiro() {
+        final Ini config = new Ini();
+        config.addSection("users");
+        config.getSection("users").put("pierre", "password, creditor");
+        config.getSection("users").put("stephane", "password, refunder");
+        config.addSection("roles");
+        config.getSection("roles").put("creditor", Permission.INVOICE_CAN_CREDIT.toString() + "," + Permission.INVOICE_CAN_ITEM_ADJUST.toString());
+        config.getSection("roles").put("refunder", Permission.PAYMENT_CAN_REFUND.toString());
+
+        // Reset the security manager
+        ThreadContext.unbindSecurityManager();
+
+        final Factory<SecurityManager> factory = new IniSecurityManagerFactory(config);
+        final SecurityManager securityManager = factory.getInstance();
+        SecurityUtils.setSecurityManager(securityManager);
+    }
 }
diff --git a/util/src/test/java/com/ning/billing/util/validation/TestValidationManager.java b/util/src/test/java/com/ning/billing/util/validation/TestValidationManager.java
index c7c8803..c639fbb 100644
--- a/util/src/test/java/com/ning/billing/util/validation/TestValidationManager.java
+++ b/util/src/test/java/com/ning/billing/util/validation/TestValidationManager.java
@@ -41,9 +41,9 @@ public class TestValidationManager extends UtilTestSuiteWithEmbeddedDB {
     @BeforeClass(groups = "slow")
     public void beforeClass() throws Exception {
         super.beforeClass();
-        final DatabaseSchemaDao dao = new DatabaseSchemaDao(getDBI());
+        final DatabaseSchemaDao dao = new DatabaseSchemaDao(dbi);
         vm = new ValidationManager(dao);
-        vm.loadSchemaInformation(helper.getDbName());
+        vm.loadSchemaInformation(helper.getDatabaseName());
     }