killbill-uncached

Add new endpoint (and matching java api) to earch for tenant

9/28/2016 4:58:44 PM

Details

diff --git a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/JaxrsResource.java b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/JaxrsResource.java
index 808aba0..071fbd0 100644
--- a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/JaxrsResource.java
+++ b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/JaxrsResource.java
@@ -34,6 +34,8 @@ public interface JaxrsResource {
     public static final String USER_KEY_VALUE = "userKeyValue";
     public static final String SEARCH = "search";
 
+    public static final String PLUGIN_CONFIG = "pluginConfig";
+
     /*
      * Multi-Tenancy headers
      */
diff --git a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/TenantResource.java b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/TenantResource.java
index fb941cc..d348596 100644
--- a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/TenantResource.java
+++ b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/TenantResource.java
@@ -16,7 +16,9 @@
 
 package org.killbill.billing.jaxrs.resources;
 
+import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
 import java.util.UUID;
 
 import javax.annotation.Nullable;
@@ -224,6 +226,26 @@ public class TenantResource extends JaxRsResourceBase {
         return deleteTenantKey(TenantKey.PLUGIN_CONFIG_, pluginName, createdBy, reason, comment, request);
     }
 
+
+    @TimedResource
+    @GET
+    @Path("/" + UPLOAD_PER_TENANT_CONFIG + "/{keyPrefix:" + ANYTHING_PATTERN + "}" + "/" + SEARCH)
+    @Produces(APPLICATION_JSON)
+    @ApiOperation(value = "Retrieve a per tenant key value based on key prefix", response = TenantKeyJson.class)
+    @ApiResponses(value = {@ApiResponse(code = 400, message = "Invalid tenantId supplied")})
+    public Response getAllPluginConfiguration(@PathParam("keyPrefix") final String keyPrefix,
+                                              @javax.ws.rs.core.Context final HttpServletRequest request) throws TenantApiException {
+
+        final TenantContext tenantContext = context.createContext(request);
+        final Map<String, List<String>> apiResult = tenantApi.searchTenantKeyValues(keyPrefix, tenantContext);
+        final List<TenantKeyJson> result = new ArrayList<TenantKeyJson>();
+        for (final String cur : apiResult.keySet()) {
+            result.add(new TenantKeyJson(cur, apiResult.get(cur)));
+        }
+        return Response.status(Status.OK).entity(result).build();
+    }
+
+
     @TimedResource
     @POST
     @Path("/" + UPLOAD_PER_TENANT_CONFIG)

pom.xml 2(+1 -1)

diff --git a/pom.xml b/pom.xml
index 0927ec9..77300c1 100644
--- a/pom.xml
+++ b/pom.xml
@@ -21,7 +21,7 @@
     <parent>
         <artifactId>killbill-oss-parent</artifactId>
         <groupId>org.kill-bill.billing</groupId>
-        <version>0.129-SNAPSHOT</version>
+        <version>0.129</version>
     </parent>
     <artifactId>killbill</artifactId>
     <version>0.17.5-SNAPSHOT</version>
diff --git a/tenant/src/main/java/org/killbill/billing/tenant/api/user/DefaultTenantUserApi.java b/tenant/src/main/java/org/killbill/billing/tenant/api/user/DefaultTenantUserApi.java
index 1fb59d8..0282ffd 100644
--- a/tenant/src/main/java/org/killbill/billing/tenant/api/user/DefaultTenantUserApi.java
+++ b/tenant/src/main/java/org/killbill/billing/tenant/api/user/DefaultTenantUserApi.java
@@ -18,7 +18,10 @@
 
 package org.killbill.billing.tenant.api.user;
 
+import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.UUID;
 
 import org.killbill.billing.ErrorCode;
@@ -32,6 +35,7 @@ import org.killbill.billing.tenant.api.TenantData;
 import org.killbill.billing.tenant.api.TenantKV.TenantKey;
 import org.killbill.billing.tenant.api.TenantUserApi;
 import org.killbill.billing.tenant.dao.TenantDao;
+import org.killbill.billing.tenant.dao.TenantKVModelDao;
 import org.killbill.billing.tenant.dao.TenantModelDao;
 import org.killbill.billing.util.cache.Cachable.CacheType;
 import org.killbill.billing.util.cache.CacheController;
@@ -147,6 +151,21 @@ public class DefaultTenantUserApi implements TenantUserApi {
         tenantKVCache.remove(tenantKey);
     }
 
+    @Override
+    public Map<String, List<String>> searchTenantKeyValues(String searchKey, TenantContext context) throws TenantApiException {
+        final InternalTenantContext internalContext = internalCallContextFactory.createInternalTenantContextWithoutAccountRecordId(context);
+        final List<TenantKVModelDao> daoResult = tenantDao.searchTenantKeyValues(searchKey, internalContext);
+        final Map<String, List<String>> result = new HashMap<String, List<String>>();
+        for (final TenantKVModelDao cur : daoResult) {
+            if (!result.containsKey(cur.getTenantKey())) {
+                result.put(cur.getTenantKey(), new ArrayList<String>());
+            }
+            result.get(cur.getTenantKey()).add(cur.getTenantValue());
+        }
+        return result;
+    }
+
+
     private List<String> getCachedTenantValuesForKey(final String key, final InternalTenantContext internalContext) {
         final String tenantKey = getCacheKeyName(key, internalContext);
         final Object cachedTenantValues = tenantKVCache.get(tenantKey, new CacheLoaderArgument(ObjectType.TENANT_KVS));
diff --git a/tenant/src/main/java/org/killbill/billing/tenant/dao/DefaultTenantDao.java b/tenant/src/main/java/org/killbill/billing/tenant/dao/DefaultTenantDao.java
index 0b6ea7d..81477ce 100644
--- a/tenant/src/main/java/org/killbill/billing/tenant/dao/DefaultTenantDao.java
+++ b/tenant/src/main/java/org/killbill/billing/tenant/dao/DefaultTenantDao.java
@@ -201,6 +201,16 @@ public class DefaultTenantDao extends EntityDaoBase<TenantModelDao, Tenant, Tena
         });
     }
 
+    @Override
+    public List<TenantKVModelDao> searchTenantKeyValues(final String searchKeyPrefix, final InternalTenantContext context) {
+        return transactionalSqlDao.execute(new EntitySqlDaoTransactionWrapper<List<TenantKVModelDao>>() {
+            @Override
+            public List<TenantKVModelDao> inTransaction(final EntitySqlDaoWrapperFactory entitySqlDaoWrapperFactory) throws Exception {
+                return entitySqlDaoWrapperFactory.become(TenantKVSqlDao.class).searchTenantKeyValues(String.format("%s%%", searchKeyPrefix), context);
+            }
+        });
+    }
+
     private Void deleteFromTransaction(final String key, final EntitySqlDaoWrapperFactory entitySqlDaoWrapperFactory, final InternalCallContext context) {
         final List<TenantKVModelDao> tenantKVs = entitySqlDaoWrapperFactory.become(TenantKVSqlDao.class).getTenantValueForKey(key, context);
         for (TenantKVModelDao cur : tenantKVs) {
diff --git a/tenant/src/main/java/org/killbill/billing/tenant/dao/NoCachingTenantDao.java b/tenant/src/main/java/org/killbill/billing/tenant/dao/NoCachingTenantDao.java
index c665cda..8f0b841 100644
--- a/tenant/src/main/java/org/killbill/billing/tenant/dao/NoCachingTenantDao.java
+++ b/tenant/src/main/java/org/killbill/billing/tenant/dao/NoCachingTenantDao.java
@@ -95,6 +95,11 @@ public class NoCachingTenantDao extends EntityDaoBase<TenantModelDao, Tenant, Te
     }
 
     @Override
+    public List<TenantKVModelDao> searchTenantKeyValues(final String searchKey, final InternalTenantContext context) {
+        throw new IllegalStateException("Not implemented by NoCachingTenantDao");
+    }
+
+    @Override
     public TenantModelDao getByRecordId(final Long recordId, final InternalTenantContext context) {
         return transactionalSqlDao.execute(new EntitySqlDaoTransactionWrapper<TenantModelDao>() {
             @Override
diff --git a/tenant/src/main/java/org/killbill/billing/tenant/dao/TenantDao.java b/tenant/src/main/java/org/killbill/billing/tenant/dao/TenantDao.java
index d52b1b3..538edbe 100644
--- a/tenant/src/main/java/org/killbill/billing/tenant/dao/TenantDao.java
+++ b/tenant/src/main/java/org/killbill/billing/tenant/dao/TenantDao.java
@@ -22,6 +22,7 @@ import org.killbill.billing.tenant.api.Tenant;
 import org.killbill.billing.tenant.api.TenantApiException;
 import org.killbill.billing.callcontext.InternalCallContext;
 import org.killbill.billing.callcontext.InternalTenantContext;
+import org.killbill.billing.util.callcontext.TenantContext;
 import org.killbill.billing.util.entity.dao.EntityDao;
 
 public interface TenantDao extends EntityDao<TenantModelDao, Tenant, TenantApiException> {
@@ -38,4 +39,6 @@ public interface TenantDao extends EntityDao<TenantModelDao, Tenant, TenantApiEx
 
     public TenantKVModelDao getKeyByRecordId(Long recordId, InternalTenantContext context);
 
+    public List<TenantKVModelDao> searchTenantKeyValues(String searchKey, InternalTenantContext context);
+
 }
diff --git a/tenant/src/main/java/org/killbill/billing/tenant/dao/TenantKVSqlDao.java b/tenant/src/main/java/org/killbill/billing/tenant/dao/TenantKVSqlDao.java
index 9e263cf..fd523cb 100644
--- a/tenant/src/main/java/org/killbill/billing/tenant/dao/TenantKVSqlDao.java
+++ b/tenant/src/main/java/org/killbill/billing/tenant/dao/TenantKVSqlDao.java
@@ -37,6 +37,11 @@ public interface TenantKVSqlDao extends EntitySqlDao<TenantKVModelDao, TenantKV>
     public List<TenantKVModelDao> getTenantValueForKey(@Bind("tenantKey") final String key,
                                                        @BindBean final InternalTenantContext context);
 
+
+    @SqlQuery
+    public List<TenantKVModelDao> searchTenantKeyValues(@Bind("tenantKeyPrefix") final String tenantKeyPrefix,
+                                                       @BindBean final InternalTenantContext context);
+
     @SqlUpdate
     @Audited(ChangeType.DELETE)
     public void markTenantKeyAsDeleted(@Bind("id")final String id,
diff --git a/tenant/src/main/resources/org/killbill/billing/tenant/dao/TenantKVSqlDao.sql.stg b/tenant/src/main/resources/org/killbill/billing/tenant/dao/TenantKVSqlDao.sql.stg
index c6aa736..9495969 100644
--- a/tenant/src/main/resources/org/killbill/billing/tenant/dao/TenantKVSqlDao.sql.stg
+++ b/tenant/src/main/resources/org/killbill/billing/tenant/dao/TenantKVSqlDao.sql.stg
@@ -40,6 +40,17 @@ and  t.is_active
 ;
 >>
 
+searchTenantKeyValues() ::= <<
+select
+  <allTableFields("t.")>
+from <tableName()> t
+where t.tenant_key like :tenantKeyPrefix
+and  t.is_active
+<AND_CHECK_TENANT("t.")>
+<defaultOrderBy("t.")>
+;
+>>
+
 markTenantKeyAsDeleted() ::= <<
 update <tableName()>
 set is_active = false
diff --git a/tenant/src/test/java/org/killbill/billing/tenant/dao/TestDefaultTenantDao.java b/tenant/src/test/java/org/killbill/billing/tenant/dao/TestDefaultTenantDao.java
index 5b56007..ed59e32 100644
--- a/tenant/src/test/java/org/killbill/billing/tenant/dao/TestDefaultTenantDao.java
+++ b/tenant/src/test/java/org/killbill/billing/tenant/dao/TestDefaultTenantDao.java
@@ -17,6 +17,7 @@
 package org.killbill.billing.tenant.dao;
 
 import java.util.List;
+import java.util.Map;
 import java.util.UUID;
 
 import org.apache.shiro.authc.AuthenticationInfo;
@@ -102,4 +103,28 @@ public class TestDefaultTenantDao extends TenantTestSuiteWithEmbeddedDb {
         Assert.assertEquals(newValues.get(1), "TheValue2");
         Assert.assertEquals(newValues.get(2), "NewValue3");
     }
+
+
+    @Test(groups = "slow")
+    public void testTenantSearch() throws Exception {
+        final DefaultTenant tenant = new DefaultTenant(UUID.randomUUID(), null, null, UUID.randomUUID().toString(),
+                                                       UUID.randomUUID().toString(), UUID.randomUUID().toString());
+        tenantDao.create(new TenantModelDao(tenant), internalCallContext);
+
+        tenantDao .addTenantKeyValue("foobar", "foobar1", false, internalCallContext);
+        tenantDao .addTenantKeyValue("foobar", "foobar2", false, internalCallContext);
+        tenantDao .addTenantKeyValue("foobar", "foobar3", false, internalCallContext);
+
+
+        tenantDao.updateTenantLastKeyValue("foo", "foo1", internalCallContext);
+
+        tenantDao.updateTenantLastKeyValue("fooXX", "fooXX1", internalCallContext);
+
+        tenantDao.updateTenantLastKeyValue("bar", "bar", internalCallContext);
+
+        final List<TenantKVModelDao> result = tenantDao.searchTenantKeyValues("foo", internalCallContext);
+        Assert.assertEquals(result.size(), 5);
+
+    }
+
 }