killbill-aplcache
Changes
server/pom.xml 11(+5 -6)
Details
diff --git a/api/src/main/java/com/ning/billing/tenant/api/TenantKV.java b/api/src/main/java/com/ning/billing/tenant/api/TenantKV.java
index 3c15086..0103440 100644
--- a/api/src/main/java/com/ning/billing/tenant/api/TenantKV.java
+++ b/api/src/main/java/com/ning/billing/tenant/api/TenantKV.java
@@ -15,11 +15,15 @@
*/
package com.ning.billing.tenant.api;
-import com.ning.billing.util.entity.Entity;
-public interface TenantKV extends Entity {
+public interface TenantKV {
public String getKey();
public String getValue();
+
+ public enum TenantKey {
+ // Key for push notification callback
+ PUSH_NOTIFICATION_CB
+ }
}
diff --git a/api/src/main/java/com/ning/billing/tenant/api/TenantUserApi.java b/api/src/main/java/com/ning/billing/tenant/api/TenantUserApi.java
index b403156..3afc712 100644
--- a/api/src/main/java/com/ning/billing/tenant/api/TenantUserApi.java
+++ b/api/src/main/java/com/ning/billing/tenant/api/TenantUserApi.java
@@ -16,9 +16,11 @@
package com.ning.billing.tenant.api;
+import java.util.List;
import java.util.UUID;
import com.ning.billing.util.callcontext.CallContext;
+import com.ning.billing.util.callcontext.TenantContext;
public interface TenantUserApi {
@@ -28,9 +30,9 @@ public interface TenantUserApi {
public Tenant getTenantById(final UUID tenantId) throws TenantApiException;
- public String getTenantValueForKey(final UUID tenantId, final String key) throws TenantApiException;
+ public List<String> getTenantValueForKey(final String key, final TenantContext context) throws TenantApiException;
- public void addTenantKeyValue(final UUID tenantId, final String key, final String value, final CallContext context) throws TenantApiException;
+ public void addTenantKeyValue(final String key, final String value, final CallContext context) throws TenantApiException;
- public void deleteTenantKey(final UUID tenantId, final String key) throws TenantApiException;
+ public void deleteTenantKey(final String key, final CallContext context) throws TenantApiException;
}
diff --git a/beatrix/src/main/java/com/ning/billing/beatrix/extbus/DefaultBusEvent.java b/beatrix/src/main/java/com/ning/billing/beatrix/extbus/DefaultBusEvent.java
index 16cd94b..6df7129 100644
--- a/beatrix/src/main/java/com/ning/billing/beatrix/extbus/DefaultBusEvent.java
+++ b/beatrix/src/main/java/com/ning/billing/beatrix/extbus/DefaultBusEvent.java
@@ -17,11 +17,11 @@ package com.ning.billing.beatrix.extbus;
import java.util.UUID;
-import com.ning.billing.beatrix.bus.api.BusEvent;
+import com.ning.billing.beatrix.bus.api.ExtBusEvent;
import com.ning.billing.beatrix.bus.api.ExtBusEventType;
import com.ning.billing.util.dao.ObjectType;
-public class DefaultBusEvent implements BusEvent {
+public class DefaultBusEvent implements ExtBusEvent {
private final ExtBusEventType eventType;
private final ObjectType objectType;
diff --git a/beatrix/src/main/java/com/ning/billing/beatrix/extbus/PersistentExternalBus.java b/beatrix/src/main/java/com/ning/billing/beatrix/extbus/PersistentExternalBus.java
index 6398289..63f1a0a 100644
--- a/beatrix/src/main/java/com/ning/billing/beatrix/extbus/PersistentExternalBus.java
+++ b/beatrix/src/main/java/com/ning/billing/beatrix/extbus/PersistentExternalBus.java
@@ -27,7 +27,7 @@ import org.skife.jdbi.v2.IDBI;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.ning.billing.beatrix.bus.api.BusEvent;
+import com.ning.billing.beatrix.bus.api.ExtBusEvent;
import com.ning.billing.beatrix.bus.api.ExternalBus;
import com.ning.billing.beatrix.extbus.dao.ExtBusEventEntry;
import com.ning.billing.beatrix.extbus.dao.ExtBusSqlDao;
@@ -121,7 +121,7 @@ public class PersistentExternalBus extends PersistentQueueBase implements Extern
// API_FIX How do we get UUID from recordId ?
final UUID accountId = null;
final UUID tenantId = null;
- final BusEvent event = new DefaultBusEvent(cur.getExtBusType(), cur.getObjectType(), cur.getObjectId(), accountId, tenantId);
+ final ExtBusEvent event = new DefaultBusEvent(cur.getExtBusType(), cur.getObjectType(), cur.getObjectId(), accountId, tenantId);
result++;
// STEPH exception handling is done by GUAVA-- logged a bug Issue-780
eventBusDelegate.post(event);
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 373fb8c..5f20021 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
@@ -99,7 +99,7 @@ public class DefaultLifecycle implements Lifecycle {
final KillbillService instance = injector.getInstance(cur);
log.info("got instance {}", instance.getName());
result.add(instance);
- } catch (Exception e) {
+ } catch (final Exception e) {
logWarn("Failed to inject " + cur.getName(), e);
}
@@ -132,7 +132,7 @@ public class DefaultLifecycle implements Lifecycle {
final KillbillService target = cur.getTarget();
log.info("Killbill lifecycle calling handler {} for service {}", cur.getMethod().getName(), target.getName());
method.invoke(target);
- } catch (Exception e) {
+ } catch (final Exception e) {
logWarn("Killbill lifecycle failed to invoke lifecycle handler", e);
}
}
@@ -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, e);
+ log.warn(msg);
}
private Multimap<LifecycleLevel, LifecycleHandler<? extends KillbillService>> findAllHandlers(final KillbillService service) {
diff --git a/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestPublicBus.java b/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestPublicBus.java
index 9b8b5c5..4faf255 100644
--- a/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestPublicBus.java
+++ b/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestPublicBus.java
@@ -27,7 +27,7 @@ import org.testng.annotations.Test;
import com.ning.billing.account.api.Account;
import com.ning.billing.api.TestApiListener.NextEvent;
-import com.ning.billing.beatrix.bus.api.BusEvent;
+import com.ning.billing.beatrix.bus.api.ExtBusEvent;
import com.ning.billing.catalog.api.BillingPeriod;
import com.ning.billing.catalog.api.PlanPhaseSpecifier;
import com.ning.billing.catalog.api.PriceListSet;
@@ -45,7 +45,7 @@ public class TestPublicBus extends TestIntegrationBase {
public class PublicListener {
@Subscribe
- public void handleExternalEvents(final BusEvent event) {
+ public void handleExternalEvents(final ExtBusEvent event) {
log.info("GOT EXT EVENT " + event.toString());
}
}
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/NotificationJson.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/NotificationJson.java
new file mode 100644
index 0000000..762a184
--- /dev/null
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/NotificationJson.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.jaxrs.json;
+
+import com.ning.billing.beatrix.bus.api.ExtBusEvent;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+/*
+ * Use to communicate back with client after they registered a callback
+ */
+public class NotificationJson {
+
+ private final String eventType;
+ private final String accountId;
+ private final String objectType;
+ private final String objectId;
+
+ @JsonCreator
+ public NotificationJson(@JsonProperty("eventType") final String eventType,
+ @JsonProperty("accountId") final String accountId,
+ @JsonProperty("objectType") final String objectType,
+ @JsonProperty("objectId") final String objectId) {
+ this.eventType = eventType;
+ this.accountId = accountId;
+ this.objectType = objectType;
+ this.objectId = objectId;
+ }
+
+
+ public NotificationJson(final ExtBusEvent event) {
+ this(event.getEventType().toString(), event.getAccountId().toString(), event.getObjectType().toString(), event.getObjectId().toString());
+ }
+
+
+ public String getEventType() {
+ return eventType;
+ }
+
+ public String getAccountId() {
+ return accountId;
+ }
+
+ public String getObjectType() {
+ return objectType;
+ }
+
+ public String getObjectId() {
+ return objectId;
+ }
+}
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/TenantKeyJson.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/TenantKeyJson.java
new file mode 100644
index 0000000..686695c
--- /dev/null
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/TenantKeyJson.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.jaxrs.json;
+
+import java.util.List;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class TenantKeyJson {
+
+ private final String key;
+ private final List<String> values;
+
+
+ @JsonCreator
+ public TenantKeyJson(@JsonProperty("key") final String key,
+ @JsonProperty("values") final List<String> values) {
+ this.key = key;
+ this.values = values;
+ }
+
+ public String getKey() {
+ return key;
+ }
+
+ public List<String> getValues() {
+ return values;
+ }
+}
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 fb16a50..8384cf9 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
@@ -25,6 +25,7 @@ public interface JaxrsResource {
public static final String PREFIX = API_PREFIX + API_VERSION + API_POSTFIX;
public static final String TIMELINE = "timeline";
+ public static final String REGISTER_NOTIFICATION_CALLBACK = "registerNotificationCallback";
/*
* Metadata Additional headers
@@ -76,6 +77,8 @@ public interface JaxrsResource {
public static final String QUERY_AUDIT = "audit";
+ public static final String QUERY_NOTIFICATION_CALLBACK = "cb";
+
public static final String ACCOUNTS = "accounts";
public static final String ACCOUNTS_PATH = PREFIX + "/" + ACCOUNTS;
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/TenantResource.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/TenantResource.java
index e94b49f..d7cbf2a 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/TenantResource.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/TenantResource.java
@@ -16,10 +16,15 @@
package com.ning.billing.jaxrs.resources;
+import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
+
+import java.net.URI;
+import java.util.List;
import java.util.UUID;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.HeaderParam;
import javax.ws.rs.POST;
@@ -29,24 +34,27 @@ import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
+import javax.ws.rs.core.UriBuilder;
import com.ning.billing.jaxrs.json.TenantJson;
+import com.ning.billing.jaxrs.json.TenantKeyJson;
import com.ning.billing.jaxrs.util.Context;
import com.ning.billing.jaxrs.util.JaxrsUriBuilder;
import com.ning.billing.tenant.api.Tenant;
import com.ning.billing.tenant.api.TenantApiException;
import com.ning.billing.tenant.api.TenantData;
+import com.ning.billing.tenant.api.TenantKV.TenantKey;
import com.ning.billing.tenant.api.TenantUserApi;
import com.ning.billing.util.api.AuditUserApi;
import com.ning.billing.util.api.CustomFieldUserApi;
import com.ning.billing.util.api.TagUserApi;
+import com.ning.billing.util.callcontext.CallContext;
+import com.ning.billing.util.callcontext.TenantContext;
import com.ning.billing.util.dao.ObjectType;
import com.google.inject.Inject;
import com.google.inject.Singleton;
-import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
-
@Singleton
@Path(JaxrsResource.TENANTS_PATH)
public class TenantResource extends JaxRsResourceBase {
@@ -55,11 +63,11 @@ public class TenantResource extends JaxRsResourceBase {
@Inject
public TenantResource(final TenantUserApi tenantApi,
- final JaxrsUriBuilder uriBuilder,
- final TagUserApi tagUserApi,
- final CustomFieldUserApi customFieldUserApi,
- final AuditUserApi auditUserApi,
- final Context context) {
+ final JaxrsUriBuilder uriBuilder,
+ final TagUserApi tagUserApi,
+ final CustomFieldUserApi customFieldUserApi,
+ final AuditUserApi auditUserApi,
+ final Context context) {
super(uriBuilder, tagUserApi, customFieldUserApi, auditUserApi, context);
this.tenantApi = tenantApi;
}
@@ -83,15 +91,55 @@ public class TenantResource extends JaxRsResourceBase {
@Consumes(APPLICATION_JSON)
@Produces(APPLICATION_JSON)
public Response createTenant(final TenantJson json,
- @HeaderParam(HDR_CREATED_BY) final String createdBy,
- @HeaderParam(HDR_REASON) final String reason,
- @HeaderParam(HDR_COMMENT) final String comment,
- @javax.ws.rs.core.Context final HttpServletRequest request) throws TenantApiException {
+ @HeaderParam(HDR_CREATED_BY) final String createdBy,
+ @HeaderParam(HDR_REASON) final String reason,
+ @HeaderParam(HDR_COMMENT) final String comment,
+ @javax.ws.rs.core.Context final HttpServletRequest request) throws TenantApiException {
final TenantData data = json.toTenantData();
final Tenant tenant = tenantApi.createTenant(data, context.createContext(createdBy, reason, comment, request));
return uriBuilder.buildResponse(TenantResource.class, "getTenant", tenant.getId());
}
+ @POST
+ @Path("/" + REGISTER_NOTIFICATION_CALLBACK)
+ @Consumes(APPLICATION_JSON)
+ @Produces(APPLICATION_JSON)
+ public Response registerPushNotificationCallback(@PathParam("tenantId") final String tenantId,
+ @QueryParam(QUERY_NOTIFICATION_CALLBACK) final String notificationCallback,
+ @HeaderParam(HDR_CREATED_BY) final String createdBy,
+ @HeaderParam(HDR_REASON) final String reason,
+ @HeaderParam(HDR_COMMENT) final String comment,
+ @javax.ws.rs.core.Context final HttpServletRequest request) throws TenantApiException {
+ final CallContext callContext = context.createContext(createdBy, reason, comment, request);
+ tenantApi.addTenantKeyValue(TenantKey.PUSH_NOTIFICATION_CB.toString(), notificationCallback, callContext);
+ final URI uri = UriBuilder.fromResource(TenantResource.class).path(TenantResource.class, "getPushNotificationCallbacks").build();
+ return Response.created(uri).build();
+ }
+
+ @GET
+ @Path("/" + REGISTER_NOTIFICATION_CALLBACK)
+ @Produces(APPLICATION_JSON)
+ public Response getPushNotificationCallbacks(@javax.ws.rs.core.Context final HttpServletRequest request) throws TenantApiException {
+
+ final TenantContext tenatContext = context.createContext(request);
+ final List<String> values = tenantApi.getTenantValueForKey(TenantKey.PUSH_NOTIFICATION_CB.toString(), tenatContext);
+ final TenantKeyJson result = new TenantKeyJson(TenantKey.PUSH_NOTIFICATION_CB.toString(), values);
+ return Response.status(Status.OK).entity(result).build();
+ }
+
+ @DELETE
+ @Path("/REGISTER_NOTIFICATION_CALLBACK")
+ public Response deletePushNotificationCallbacks(@PathParam("tenantId") final String tenantId,
+ @HeaderParam(HDR_CREATED_BY) final String createdBy,
+ @HeaderParam(HDR_REASON) final String reason,
+ @HeaderParam(HDR_COMMENT) final String comment,
+ @javax.ws.rs.core.Context final HttpServletRequest request) throws TenantApiException {
+ final CallContext callContext = context.createContext(createdBy, reason, comment, request);
+ tenantApi.deleteTenantKey(TenantKey.PUSH_NOTIFICATION_CB.toString(), callContext);
+ return Response.status(Status.OK).build();
+ }
+
+
@Override
protected ObjectType getObjectType() {
return ObjectType.TENANT;
diff --git a/overdue/src/main/java/com/ning/billing/overdue/glue/DefaultOverdueModule.java b/overdue/src/main/java/com/ning/billing/overdue/glue/DefaultOverdueModule.java
index 08920d8..e83cbbf 100644
--- a/overdue/src/main/java/com/ning/billing/overdue/glue/DefaultOverdueModule.java
+++ b/overdue/src/main/java/com/ning/billing/overdue/glue/DefaultOverdueModule.java
@@ -31,7 +31,6 @@ import com.ning.billing.overdue.applicator.OverdueEmailGenerator;
import com.ning.billing.overdue.applicator.formatters.DefaultOverdueEmailFormatterFactory;
import com.ning.billing.overdue.applicator.formatters.OverdueEmailFormatterFactory;
import com.ning.billing.overdue.service.DefaultOverdueService;
-import com.ning.billing.overdue.service.ExtendedOverdueService;
import com.ning.billing.overdue.wrapper.OverdueWrapperFactory;
import com.google.inject.AbstractModule;
@@ -49,7 +48,7 @@ public class DefaultOverdueModule extends AbstractModule implements OverdueModul
final OverdueProperties config = new ConfigurationObjectFactory(System.getProperties()).build(OverdueProperties.class);
bind(OverdueProperties.class).toInstance(config);
- bind(ExtendedOverdueService.class).to(DefaultOverdueService.class).asEagerSingleton();
+ //bind(ExtendedOverdueService.class).to(DefaultOverdueService.class).asEagerSingleton();
bind(OverdueCheckNotifier.class).to(DefaultOverdueCheckNotifier.class).asEagerSingleton();
bind(OverdueCheckPoster.class).to(DefaultOverdueCheckPoster.class).asEagerSingleton();
}
diff --git a/overdue/src/main/java/com/ning/billing/overdue/service/DefaultOverdueService.java b/overdue/src/main/java/com/ning/billing/overdue/service/DefaultOverdueService.java
index c0879ad..c3ea860 100644
--- a/overdue/src/main/java/com/ning/billing/overdue/service/DefaultOverdueService.java
+++ b/overdue/src/main/java/com/ning/billing/overdue/service/DefaultOverdueService.java
@@ -22,21 +22,23 @@ import java.net.URISyntaxException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.google.inject.Inject;
import com.ning.billing.lifecycle.LifecycleHandlerType;
import com.ning.billing.lifecycle.LifecycleHandlerType.LifecycleLevel;
import com.ning.billing.ovedue.notification.OverdueCheckNotifier;
import com.ning.billing.overdue.OverdueProperties;
+import com.ning.billing.overdue.OverdueService;
import com.ning.billing.overdue.OverdueUserApi;
import com.ning.billing.overdue.api.DefaultOverdueUserApi;
import com.ning.billing.overdue.config.OverdueConfig;
import com.ning.billing.overdue.listener.OverdueListener;
import com.ning.billing.overdue.wrapper.OverdueWrapperFactory;
-import com.ning.billing.util.svcsapi.bus.InternalBus.EventBusException;
-import com.ning.billing.util.svcsapi.bus.BusService;
import com.ning.billing.util.config.XMLLoader;
+import com.ning.billing.util.svcsapi.bus.BusService;
+import com.ning.billing.util.svcsapi.bus.InternalBus.EventBusException;
+
+import com.google.inject.Inject;
-public class DefaultOverdueService implements ExtendedOverdueService {
+public class DefaultOverdueService implements OverdueService {
private static final Logger log = LoggerFactory.getLogger(DefaultOverdueService.class);
public static final String OVERDUE_SERVICE_NAME = "overdue-service";
@@ -48,7 +50,7 @@ public class DefaultOverdueService implements ExtendedOverdueService {
private final OverdueWrapperFactory factory;
private OverdueConfig overdueConfig;
- private boolean isInitialized;
+ private boolean isConfigLoaded;
@Inject
public DefaultOverdueService(
@@ -64,6 +66,7 @@ public class DefaultOverdueService implements ExtendedOverdueService {
this.busService = busService;
this.listener = listener;
this.factory = factory;
+ this.isConfigLoaded = false;
}
@Override
@@ -76,14 +79,14 @@ public class DefaultOverdueService implements ExtendedOverdueService {
return userApi;
}
- @Override
+ //@Override
public OverdueConfig getOverdueConfig() {
return overdueConfig;
}
- @LifecycleHandlerType(LifecycleLevel.INIT_SERVICE)
+ @LifecycleHandlerType(LifecycleLevel.LOAD_CATALOG)
public synchronized void loadConfig() throws ServiceException {
- if (!isInitialized) {
+ if (!isConfigLoaded) {
try {
final URI u = new URI(properties.getConfigURI());
overdueConfig = XMLLoader.getObjectFromUri(u, OverdueConfig.class);
@@ -93,12 +96,12 @@ public class DefaultOverdueService implements ExtendedOverdueService {
overdueConfig = new OverdueConfig();
}
- isInitialized = true;
- } catch (URISyntaxException e) {
+ isConfigLoaded = true;
+ } catch (final URISyntaxException e) {
overdueConfig = new OverdueConfig();
- } catch (IllegalArgumentException e) {
+ } catch (final IllegalArgumentException e) {
overdueConfig = new OverdueConfig();
- } catch (Exception e) {
+ } catch (final Exception e) {
throw new ServiceException(e);
}
@@ -121,7 +124,7 @@ public class DefaultOverdueService implements ExtendedOverdueService {
public void registerForBus() {
try {
busService.getBus().register(listener);
- } catch (EventBusException e) {
+ } catch (final EventBusException e) {
log.error("Problem encountered registering OverdueListener on the Event Bus", e);
}
}
@@ -130,7 +133,7 @@ public class DefaultOverdueService implements ExtendedOverdueService {
public void unregisterForBus() {
try {
busService.getBus().unregister(listener);
- } catch (EventBusException e) {
+ } catch (final EventBusException e) {
log.error("Problem encountered registering OverdueListener on the Event Bus", e);
}
}
server/pom.xml 11(+5 -6)
diff --git a/server/pom.xml b/server/pom.xml
index a519a55..25b4148 100644
--- a/server/pom.xml
+++ b/server/pom.xml
@@ -127,6 +127,11 @@
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
+ <groupId>com.ning</groupId>
+ <artifactId>async-http-client</artifactId>
+ <version>${async-http-client.version}</version>
+ </dependency>
+ <dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>${slf4j.version}</version>
@@ -241,12 +246,6 @@
<artifactId>shiro-web</artifactId>
</dependency>
<dependency>
- <groupId>com.ning</groupId>
- <artifactId>async-http-client</artifactId>
- <version>${async-http-client.version}</version>
- <scope>test</scope>
- </dependency>
- <dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<scope>test</scope>
diff --git a/server/src/main/java/com/ning/billing/server/DefaultServerService.java b/server/src/main/java/com/ning/billing/server/DefaultServerService.java
new file mode 100644
index 0000000..98a3c4c
--- /dev/null
+++ b/server/src/main/java/com/ning/billing/server/DefaultServerService.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+package com.ning.billing.server;
+
+import javax.inject.Inject;
+
+import com.ning.billing.beatrix.bus.api.ExternalBus;
+import com.ning.billing.lifecycle.LifecycleHandlerType;
+import com.ning.billing.server.notifications.PushNotificationListener;
+
+public class DefaultServerService implements ServerService {
+
+ private final static String SERVER_SERVICE = "server-service";
+
+
+ private final ExternalBus bus;
+ private final PushNotificationListener pushNotificationListener;
+
+ @Inject
+ public DefaultServerService(final ExternalBus bus, final PushNotificationListener pushNotificationListener) {
+ this.bus = bus;
+ this.pushNotificationListener = pushNotificationListener;
+ }
+
+ @Override
+ public String getName() {
+ return SERVER_SERVICE;
+ }
+
+ @LifecycleHandlerType(LifecycleHandlerType.LifecycleLevel.REGISTER_EVENTS)
+ public void registerForNotifications() {
+ bus.register(pushNotificationListener);
+ }
+
+ @LifecycleHandlerType(LifecycleHandlerType.LifecycleLevel.UNREGISTER_EVENTS)
+ public void unregisterForNotifications() {
+ bus.unregister(pushNotificationListener);
+ }
+}
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 4676cb4..5a25746 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
@@ -40,6 +40,9 @@ import com.ning.billing.jaxrs.util.KillbillEventHandler;
import com.ning.billing.junction.glue.DefaultJunctionModule;
import com.ning.billing.overdue.glue.DefaultOverdueModule;
import com.ning.billing.payment.glue.PaymentModule;
+import com.ning.billing.server.DefaultServerService;
+import com.ning.billing.server.ServerService;
+import com.ning.billing.server.notifications.PushNotificationListener;
import com.ning.billing.tenant.glue.TenantModule;
import com.ning.billing.util.email.EmailModule;
import com.ning.billing.util.email.templates.TemplateModule;
@@ -62,6 +65,13 @@ public class KillbillServerModule extends AbstractModule {
configureDao();
configureResources();
installKillbillModules();
+ configurePushNotification();
+ }
+
+
+ protected void configurePushNotification() {
+ bind(ServerService.class).to(DefaultServerService.class).asEagerSingleton();
+ bind(PushNotificationListener.class).asEagerSingleton();
}
@@ -69,7 +79,7 @@ public class KillbillServerModule extends AbstractModule {
// Load mysql driver if needed
try {
Class.forName ("com.mysql.jdbc.Driver").newInstance ();
- } catch (Exception ignore) {
+ } catch (final Exception ignore) {
}
bind(IDBI.class).to(DBI.class).asEagerSingleton();
bind(DBI.class).toProvider(DBIProvider.class).asEagerSingleton();
diff --git a/server/src/main/java/com/ning/billing/server/notifications/PushNotificationListener.java b/server/src/main/java/com/ning/billing/server/notifications/PushNotificationListener.java
new file mode 100644
index 0000000..3f6fe43
--- /dev/null
+++ b/server/src/main/java/com/ning/billing/server/notifications/PushNotificationListener.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+package com.ning.billing.server.notifications;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.UUID;
+import java.util.concurrent.TimeUnit;
+
+import javax.inject.Inject;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.ning.billing.beatrix.bus.api.ExtBusEvent;
+import com.ning.billing.jaxrs.json.NotificationJson;
+import com.ning.billing.tenant.api.TenantApiException;
+import com.ning.billing.tenant.api.TenantKV.TenantKey;
+import com.ning.billing.tenant.api.TenantUserApi;
+import com.ning.billing.util.callcontext.CallContextFactory;
+import com.ning.billing.util.callcontext.TenantContext;
+import com.ning.http.client.AsyncCompletionHandler;
+import com.ning.http.client.AsyncHttpClient;
+import com.ning.http.client.AsyncHttpClient.BoundRequestBuilder;
+import com.ning.http.client.AsyncHttpClientConfig;
+import com.ning.http.client.ListenableFuture;
+import com.ning.http.client.Response;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.common.eventbus.Subscribe;
+
+public class PushNotificationListener {
+
+ private final static Logger log = LoggerFactory.getLogger(PushNotificationListener.class);
+
+ private final static int TIMEOUT_NOTIFCATION = 15; // 15 seconds
+
+ private final TenantUserApi tenantApi;
+ private final CallContextFactory contextFactory;
+ private final AsyncHttpClient httpClient;
+ private final ObjectMapper mapper;
+
+
+ @Inject
+ public PushNotificationListener(final ObjectMapper mapper, final TenantUserApi tenantApi, final CallContextFactory contextFactory) {
+ this.httpClient = new AsyncHttpClient(new AsyncHttpClientConfig.Builder().setRequestTimeoutInMs(TIMEOUT_NOTIFCATION * 1000).build());
+ this.tenantApi = tenantApi;
+ this.contextFactory = contextFactory;
+ this.mapper = mapper;
+ }
+
+ @Subscribe
+ public void triggerPushNotifications(final ExtBusEvent event) {
+ final TenantContext context = contextFactory.createTenantContext(event.getTenantId());
+ try {
+ final List<String> callbacks = getCallbacksForTenant(context);
+ dispatchCallback(event.getTenantId(), event, callbacks);
+ } catch (final TenantApiException e) {
+ log.warn("Failed to retrieve push notification callback for tenant {}", event.getTenantId());
+ } catch (final IOException e) {
+ log.warn("Failed to retrieve push notification callback for tenant {}", event.getTenantId());
+ }
+ }
+
+ private void dispatchCallback(final UUID tenantId, final ExtBusEvent event, final List<String> callbacks) throws IOException {
+ final NotificationJson notification = new NotificationJson(event);
+ final String body = mapper.writeValueAsString(notification);
+ for (final String cur : callbacks) {
+ doPost(tenantId, cur, body, TIMEOUT_NOTIFCATION);
+ }
+ }
+
+
+ private boolean doPost(final UUID tenantId, final String url, final String body, final int timeoutSec) {
+
+ final BoundRequestBuilder builder = httpClient.preparePost(url);
+ builder.setBody(body == null ? "{}" : body);
+
+ Response response = null;
+ try {
+ final ListenableFuture<Response> futureStatus =
+ builder.execute(new AsyncCompletionHandler<Response>() {
+ @Override
+ public Response onCompleted(final Response response) throws Exception {
+ return response;
+ }
+ });
+ response = futureStatus.get(timeoutSec, TimeUnit.SECONDS);
+ } catch (final Exception e) {
+ log.warn(String.format("Fail to psh notification {} for the tenant {} ", url, tenantId), e);
+ return false;
+ }
+ return response.getStatusCode() >= 200 && response.getStatusCode() < 300;
+ }
+
+ private List<String> getCallbacksForTenant(final TenantContext context) throws TenantApiException {
+ return tenantApi.getTenantValueForKey(TenantKey.PUSH_NOTIFICATION_CB.toString(), context);
+ }
+}
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 53bb288..9062bf8 100644
--- a/server/src/test/java/com/ning/billing/jaxrs/KillbillClient.java
+++ b/server/src/test/java/com/ning/billing/jaxrs/KillbillClient.java
@@ -16,6 +16,13 @@
package com.ning.billing.jaxrs;
+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.QUERY_PAYMENT_METHOD_PLUGIN_INFO;
+import static com.ning.billing.jaxrs.resources.JaxrsResource.SUBSCRIPTIONS;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+
import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
@@ -76,13 +83,6 @@ import com.google.common.base.Function;
import com.google.common.collect.Collections2;
import com.google.common.collect.ImmutableMap;
-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.QUERY_PAYMENT_METHOD_PLUGIN_INFO;
-import static com.ning.billing.jaxrs.resources.JaxrsResource.SUBSCRIPTIONS;
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertNotNull;
-
public abstract class KillbillClient extends ServerTestSuiteWithEmbeddedDB {
protected static final String PLUGIN_NAME = "noop";
@@ -142,10 +142,21 @@ public abstract class KillbillClient extends ServerTestSuiteWithEmbeddedDB {
// TENANT UTILITIES
//
- protected void createTenant(final String apiKey, final String apiSecret) throws Exception {
+ protected String createTenant(final String apiKey, final String apiSecret) throws Exception {
final String baseJson = mapper.writeValueAsString(new TenantJson(null, null, apiKey, apiSecret));
final Response response = doPost(JaxrsResource.TENANTS_PATH, baseJson, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
Assert.assertEquals(response.getStatusCode(), Status.CREATED.getStatusCode());
+ return response.getHeader("Location");
+ }
+
+
+ protected String registerCallbackNotificationForTenant(final String callback) throws Exception {
+ final Map<String, String> queryParams = new HashMap<String, String>();
+ queryParams.put(JaxrsResource.QUERY_NOTIFICATION_CALLBACK, callback);
+ final String uri = JaxrsResource.TENANTS_PATH + "/" + JaxrsResource.REGISTER_NOTIFICATION_CALLBACK ;
+ final Response response = doPost(uri, null, queryParams, DEFAULT_HTTP_TIMEOUT_SEC);
+ Assert.assertEquals(response.getStatusCode(), Status.CREATED.getStatusCode());
+ return response.getHeader("Location");
}
//
@@ -841,7 +852,7 @@ public abstract class KillbillClient extends ServerTestSuiteWithEmbeddedDB {
}
});
response = futureStatus.get(timeoutSec, TimeUnit.SECONDS);
- } catch (Exception e) {
+ } catch (final Exception e) {
Assert.fail(e.getMessage());
}
Assert.assertNotNull(response);
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 eb0b9c1..6384d8f 100644
--- a/server/src/test/java/com/ning/billing/jaxrs/TestJaxrsBase.java
+++ b/server/src/test/java/com/ning/billing/jaxrs/TestJaxrsBase.java
@@ -16,8 +16,9 @@
package com.ning.billing.jaxrs;
+import static org.testng.Assert.assertNotNull;
+
import java.io.IOException;
-import java.lang.reflect.Method;
import java.net.URL;
import java.util.EventListener;
import java.util.HashMap;
@@ -77,8 +78,6 @@ import com.fasterxml.jackson.datatype.joda.JodaModule;
import com.google.common.collect.ImmutableList;
import com.google.inject.Module;
-import static org.testng.Assert.assertNotNull;
-
public class TestJaxrsBase extends KillbillClient {
protected static final String PLUGIN_NAME = "noop";
@@ -97,7 +96,7 @@ public class TestJaxrsBase extends KillbillClient {
assertNotNull(url);
try {
System.getProperties().load(url.openStream());
- } catch (IOException e) {
+ } catch (final IOException e) {
throw new RuntimeException(e);
}
}
@@ -202,7 +201,7 @@ public class TestJaxrsBase extends KillbillClient {
}
@BeforeMethod(groups = "slow")
- public void cleanupBeforeMethod(final Method method) {
+ public void cleanupBeforeMethod() {
busHandler.reset();
clock.reset();
clock.setDay(new LocalDate(2012, 8, 25));
@@ -264,7 +263,7 @@ public class TestJaxrsBase extends KillbillClient {
public void tearDown() {
try {
server.stop();
- } catch (Exception ignored) {
+ } catch (final Exception ignored) {
}
}
}
diff --git a/server/src/test/java/com/ning/billing/jaxrs/TestJetty.java b/server/src/test/java/com/ning/billing/jaxrs/TestJetty.java
new file mode 100644
index 0000000..75186e0
--- /dev/null
+++ b/server/src/test/java/com/ning/billing/jaxrs/TestJetty.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+package com.ning.billing.jaxrs;
+
+import java.io.IOException;
+import java.io.InputStreamReader;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.servlet.ServletContextHandler;
+import org.eclipse.jetty.servlet.ServletHolder;
+
+import com.google.common.io.CharStreams;
+
+public class TestJetty {
+
+ public TestJetty() {
+
+ }
+
+ public static void main(final String [] args) throws Exception {
+
+ final Server server = new Server(8080);
+
+ final ServletContextHandler context = new ServletContextHandler();
+ context.setContextPath("/");
+ server.setHandler(context);
+
+ context.addServlet(new ServletHolder(new CallmebackServlet()),"/callmeback");
+
+ server.start();
+ server.join();
+ }
+
+
+ public static class CallmebackServlet extends HttpServlet
+ {
+ public CallmebackServlet() {
+ }
+
+ @Override
+ protected void doPost(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException
+ {
+ final String body = CharStreams.toString( new InputStreamReader(request.getInputStream(), "UTF-8" ));
+ System.out.print("Got " + body);
+
+
+ response.setContentType("application/json");
+ response.setStatus(HttpServletResponse.SC_OK);
+ response.getWriter().println("{\"key\"=12}");
+ }
+ }
+
+}
diff --git a/server/src/test/java/com/ning/billing/jaxrs/TestTenant.java b/server/src/test/java/com/ning/billing/jaxrs/TestTenant.java
new file mode 100644
index 0000000..0dfd744
--- /dev/null
+++ b/server/src/test/java/com/ning/billing/jaxrs/TestTenant.java
@@ -0,0 +1,161 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+package com.ning.billing.jaxrs;
+
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.servlet.ServletContextHandler;
+import org.eclipse.jetty.servlet.ServletHolder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import com.google.common.io.CharStreams;
+
+public class TestTenant extends TestJaxrsBase {
+
+
+ private CallbackServer callbackServer;
+
+ private final static int SERVER_PORT = 8087;
+ private final static String CALLBACK_ENDPPOINT = "/callmeback";
+
+
+ @BeforeMethod(groups = "slow")
+ public void startServer() throws Exception {
+ callbackServer = new CallbackServer(SERVER_PORT, CALLBACK_ENDPPOINT, null);
+ //callbackServer.startServer();
+ }
+
+ @AfterMethod(groups = "slow")
+ public void stopServer() throws Exception {
+ //callbackServer.stopServer();
+ }
+
+ @Test(groups = "slow")
+ public void testTenant() throws Exception {
+
+ /*
+ final String apiKeyTenant = "yoyo";
+ final String apiSecretTenant = "yoyoisf3ommars";
+
+ final String location = createTenant(apiKeyTenant, apiSecretTenant);
+ Assert.assertNotNull(location);
+
+ final String tenantId = extractTenantIdFromLocation(location);
+
+ // Retrieves by Id based on Location returned
+ final Response response = doGetWithUrl(location, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
+ Assert.assertEquals(response.getStatusCode(), Status.OK.getStatusCode());
+*/
+
+ registerCallbackNotificationForTenant("http://127.0.0.1:" + SERVER_PORT + CALLBACK_ENDPPOINT);
+
+ // Excellent, now create an account and check that callback is called
+ createAccount();
+
+ }
+
+ private String extractTenantIdFromLocation(final String location) {
+ final String [] parts = location.split("/");
+ return parts[parts.length - 1];
+ }
+
+
+ public class CallbackServer {
+
+ private final Server server;
+ private final String callbackEndpoint;
+ private final String expectedTenantId;
+
+ public CallbackServer(final int port, final String callbackEndpoint, final String expectedTenantId) {
+ this.callbackEndpoint = callbackEndpoint;
+ this.expectedTenantId = expectedTenantId;
+ this.server = new Server(port);
+ }
+
+ public void startServer() throws Exception {
+ final ServletContextHandler context = new ServletContextHandler();
+ context.setContextPath("/");
+ server.setHandler(context);
+ context.addServlet(new ServletHolder(new CallmebackServlet(server, expectedTenantId, 1)), callbackEndpoint);
+ server.start();
+ server.join();
+ }
+
+ public void stopServer() throws Exception {
+ server.stop();
+ }
+ }
+
+
+ public static class CallmebackServlet extends HttpServlet {
+
+ private static final long serialVersionUID = -5181211514918217301L;
+
+ private final static Logger log = LoggerFactory.getLogger(CallmebackServlet.class);
+
+ private final Server server;
+ private final String expectedTenantId;
+ private final int expectedNbCalls;
+ private final AtomicInteger receivedCalls;
+
+ public CallmebackServlet(final Server server, final String expectedTenantId, final int expectedNbCalls) {
+ this.server = server;
+ this.expectedTenantId = expectedTenantId;
+ this.expectedNbCalls = expectedNbCalls;
+ this.receivedCalls = new AtomicInteger(0);
+ }
+
+ @Override
+ protected void doPost(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException
+ {
+
+ final int current = receivedCalls.incrementAndGet();
+
+ final String body = CharStreams.toString( new InputStreamReader(request.getInputStream(), "UTF-8" ));
+
+ log.info("CallmebackServlet received {} calls , current = {}", current, body);
+
+ response.setContentType("application/json");
+ response.setStatus(HttpServletResponse.SC_OK);
+
+ stopServerWhenComplete(current);
+ }
+
+
+ private void stopServerWhenComplete(final int current) {
+ if (current == expectedNbCalls) {
+ try {
+ server.stop();
+ log.info("Callmeback server stopped succesfully");
+ } catch (final Exception e) {
+ log.warn("Failed to stop jetty Callmeback server");
+ }
+ }
+ }
+ }
+}
diff --git a/tenant/src/main/java/com/ning/billing/tenant/api/DefaultTenantKV.java b/tenant/src/main/java/com/ning/billing/tenant/api/DefaultTenantKV.java
index cbf185d..ece3445 100644
--- a/tenant/src/main/java/com/ning/billing/tenant/api/DefaultTenantKV.java
+++ b/tenant/src/main/java/com/ning/billing/tenant/api/DefaultTenantKV.java
@@ -15,19 +15,13 @@
*/
package com.ning.billing.tenant.api;
-import java.util.UUID;
-import org.joda.time.DateTime;
-
-import com.ning.billing.util.entity.EntityBase;
-
-public class DefaultTenantKV extends EntityBase implements TenantKV {
+public class DefaultTenantKV implements TenantKV {
private final String key;
private final String value;
- public DefaultTenantKV(final UUID tenantId, final String key, final String value, final DateTime createdDate, final DateTime updatedDate) {
- super(tenantId, createdDate, updatedDate);
+ public DefaultTenantKV(final String key, final String value) {
this.key = key;
this.value = value;
}
diff --git a/tenant/src/main/java/com/ning/billing/tenant/api/user/DefaultTenantUserApi.java b/tenant/src/main/java/com/ning/billing/tenant/api/user/DefaultTenantUserApi.java
index 7273fd5..5c00812 100644
--- a/tenant/src/main/java/com/ning/billing/tenant/api/user/DefaultTenantUserApi.java
+++ b/tenant/src/main/java/com/ning/billing/tenant/api/user/DefaultTenantUserApi.java
@@ -16,6 +16,7 @@
package com.ning.billing.tenant.api.user;
+import java.util.List;
import java.util.UUID;
import com.ning.billing.ErrorCode;
@@ -29,6 +30,7 @@ import com.ning.billing.util.callcontext.CallContext;
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.TenantContext;
import com.ning.billing.util.entity.EntityPersistenceException;
import com.google.inject.Inject;
@@ -44,6 +46,7 @@ public class DefaultTenantUserApi implements TenantUserApi {
this.internalCallContextFactory = internalCallContextFactory;
}
+
@Override
public Tenant createTenant(final TenantData data, final CallContext context) throws TenantApiException {
final Tenant tenant = new DefaultTenant(data);
@@ -77,35 +80,39 @@ public class DefaultTenantUserApi implements TenantUserApi {
}
@Override
- public String getTenantValueForKey(final UUID tenantId, final String key)
+ public List<String> getTenantValueForKey(final String key, final TenantContext context)
throws TenantApiException {
- final String value = tenantDao.getTenantValueForKey(tenantId, key);
- if (value == null) {
- throw new TenantApiException(ErrorCode.TENANT_NO_SUCH_KEY, tenantId, key);
- }
+ final InternalTenantContext internalContext = internalCallContextFactory.createInternalTenantContext(context);
+ final List<String> value = tenantDao.getTenantValueForKey(key, internalContext);
return value;
}
@Override
- public void addTenantKeyValue(final UUID tenantId, final String key, final String value, final CallContext context)
+ public void addTenantKeyValue(final String key, final String value, final CallContext context)
throws TenantApiException {
- final InternalCallContext internalContext = new InternalCallContext(null, null, context);
- final Tenant tenant = tenantDao.getById(tenantId, internalContext);
+ final InternalCallContext internalContext = internalCallContextFactory.createInternalCallContext(context);
+ // TODO Figure out the exact verification if nay
+ /*
+ final Tenant tenant = tenantDao.getById(context.getTenantId(), internalContext);
if (tenant == null) {
throw new TenantApiException(ErrorCode.TENANT_DOES_NOT_EXIST_FOR_ID, tenantId);
}
- tenantDao.addTenantKeyValue(tenantId, key, value, internalContext);
+ */
+ tenantDao.addTenantKeyValue(key, value, internalContext);
}
@Override
- public void deleteTenantKey(final UUID tenantId, final String key)
+ public void deleteTenantKey(final String key, final CallContext context)
throws TenantApiException {
+ /*
final Tenant tenant = tenantDao.getById(tenantId, new InternalTenantContext(null, null));
if (tenant == null) {
throw new TenantApiException(ErrorCode.TENANT_DOES_NOT_EXIST_FOR_ID, tenantId);
}
- tenantDao.deleteTenantKey(tenantId, key);
+ */
+ final InternalCallContext internalContext = internalCallContextFactory.createInternalCallContext(context);
+ tenantDao.deleteTenantKey(key, internalContext);
}
}
diff --git a/tenant/src/main/java/com/ning/billing/tenant/dao/DefaultTenantDao.java b/tenant/src/main/java/com/ning/billing/tenant/dao/DefaultTenantDao.java
index 6890832..6f59f17 100644
--- a/tenant/src/main/java/com/ning/billing/tenant/dao/DefaultTenantDao.java
+++ b/tenant/src/main/java/com/ning/billing/tenant/dao/DefaultTenantDao.java
@@ -19,6 +19,8 @@ package com.ning.billing.tenant.dao;
import java.util.List;
import java.util.UUID;
+import javax.annotation.Nullable;
+
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.crypto.RandomNumberGenerator;
import org.apache.shiro.crypto.SecureRandomNumberGenerator;
@@ -36,6 +38,9 @@ import com.ning.billing.util.entity.EntityPersistenceException;
import com.ning.billing.util.svcsapi.bus.InternalBus;
import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Function;
+import com.google.common.collect.Collections2;
+import com.google.common.collect.ImmutableList;
import com.google.inject.Inject;
public class DefaultTenantDao implements TenantDao {
@@ -97,21 +102,24 @@ public class DefaultTenantDao implements TenantDao {
}
@Override
- public String getTenantValueForKey(final UUID tenantId, final String key) {
- final TenantKV tenantKV = tenantKVSqlDao.getTenantValueForKey(tenantId.toString(), key);
- if (tenantKV == null) {
- return null;
- }
- return tenantKV.getValue();
+ public List<String> getTenantValueForKey(final String key, final InternalTenantContext context) {
+ final List<TenantKV> tenantKV = tenantKVSqlDao.getTenantValueForKey(key, context.getTenantRecordId());
+ return ImmutableList.copyOf(Collections2.transform(tenantKV, new Function<TenantKV, String>() {
+ @Override
+ @Nullable
+ public String apply(final @Nullable TenantKV in) {
+ return in.getValue();
+ }
+ }));
}
@Override
- public void addTenantKeyValue(final UUID tenantId, final String key, final String value, final InternalCallContext context) {
- tenantKVSqlDao.insertTenantKeyValue(tenantId.toString(), key, value, context);
+ public void addTenantKeyValue(final String key, final String value, final InternalCallContext context) {
+ tenantKVSqlDao.insertTenantKeyValue(key, value, context.getTenantRecordId(), context);
}
@Override
- public void deleteTenantKey(final UUID tenantId, final String key) {
- tenantKVSqlDao.deleteTenantKey(tenantId.toString(), key);
+ public void deleteTenantKey(final String key, final InternalCallContext context) {
+ tenantKVSqlDao.deleteTenantKey(key, context.getTenantRecordId());
}
}
diff --git a/tenant/src/main/java/com/ning/billing/tenant/dao/TenantDao.java b/tenant/src/main/java/com/ning/billing/tenant/dao/TenantDao.java
index c73b52f..0d0add0 100644
--- a/tenant/src/main/java/com/ning/billing/tenant/dao/TenantDao.java
+++ b/tenant/src/main/java/com/ning/billing/tenant/dao/TenantDao.java
@@ -16,19 +16,20 @@
package com.ning.billing.tenant.dao;
-import java.util.UUID;
+import java.util.List;
import com.ning.billing.tenant.api.Tenant;
import com.ning.billing.util.callcontext.InternalCallContext;
+import com.ning.billing.util.callcontext.InternalTenantContext;
import com.ning.billing.util.entity.dao.EntityDao;
public interface TenantDao extends EntityDao<Tenant> {
public Tenant getTenantByApiKey(final String key);
- public String getTenantValueForKey(final UUID tenantId, final String key);
+ public List<String> getTenantValueForKey(final String key, final InternalTenantContext context);
- public void addTenantKeyValue(final UUID tenantId, final String key, final String value, final InternalCallContext context);
+ public void addTenantKeyValue(final String key, final String value, final InternalCallContext context);
- public void deleteTenantKey(final UUID tenantId, final String key);
+ public void deleteTenantKey(final String key, final InternalCallContext context);
}
diff --git a/tenant/src/main/java/com/ning/billing/tenant/dao/TenantKVSqlDao.java b/tenant/src/main/java/com/ning/billing/tenant/dao/TenantKVSqlDao.java
index 1535ffd..83b3d79 100644
--- a/tenant/src/main/java/com/ning/billing/tenant/dao/TenantKVSqlDao.java
+++ b/tenant/src/main/java/com/ning/billing/tenant/dao/TenantKVSqlDao.java
@@ -17,9 +17,8 @@ package com.ning.billing.tenant.dao;
import java.sql.ResultSet;
import java.sql.SQLException;
-import java.util.UUID;
+import java.util.List;
-import org.joda.time.DateTime;
import org.skife.jdbi.v2.StatementContext;
import org.skife.jdbi.v2.sqlobject.Bind;
import org.skife.jdbi.v2.sqlobject.SqlQuery;
@@ -36,33 +35,28 @@ import com.ning.billing.util.callcontext.InternalCallContext;
import com.ning.billing.util.callcontext.InternalTenantContextBinder;
import com.ning.billing.util.dao.MapperBase;
import com.ning.billing.util.dao.UuidMapper;
-import com.ning.billing.util.entity.dao.EntitySqlDao;
@ExternalizedSqlViaStringTemplate3
@RegisterMapper({UuidMapper.class, TenantKVMapper.class})
-public interface TenantKVSqlDao extends EntitySqlDao<TenantKV>, Transactional<TenantKVSqlDao> {
+public interface TenantKVSqlDao extends Transactional<TenantKVSqlDao> {
@SqlQuery
- public TenantKV getTenantValueForKey(@Bind("id") final String tenantId, @Bind("key") final String key);
+ public List<TenantKV> getTenantValueForKey(@Bind("key") final String key, @Bind("tenantRecordId") Long tenantRecordId);
@SqlUpdate
- public void insertTenantKeyValue(@Bind("id") final String tenantId, @Bind("key") final String key, @Bind("value") final String value,
- @InternalTenantContextBinder final InternalCallContext context);
+ public void insertTenantKeyValue(@Bind("key") final String key, @Bind("value") final String value, @Bind("tenantRecordId") Long tenantRecordId, @InternalTenantContextBinder final InternalCallContext context);
@SqlUpdate
- public void deleteTenantKey(@Bind("id") final String tenantId, @Bind("key") final String key);
+ public void deleteTenantKey(@Bind("key") final String key, @Bind("tenantRecordId") Long tenantRecordId);
public class TenantKVMapper extends MapperBase implements ResultSetMapper<TenantKV> {
@Override
public TenantKV map(final int index, final ResultSet result, final StatementContext context) throws SQLException {
- final UUID id = getUUID(result, "id");
final String key = result.getString("t_key");
final String value = result.getString("t_value");
- final DateTime createdDate = getDateTime(result, "created_date");
- final DateTime updatedDate = getDateTime(result, "updated_date");
- return new DefaultTenantKV(id, key, value, createdDate, updatedDate);
+ return new DefaultTenantKV(key, value);
}
}
}
diff --git a/tenant/src/main/resources/com/ning/billing/tenant/dao/TenantKVSqlDao.sql.stg b/tenant/src/main/resources/com/ning/billing/tenant/dao/TenantKVSqlDao.sql.stg
index 3e2d0cb..432267f 100644
--- a/tenant/src/main/resources/com/ning/billing/tenant/dao/TenantKVSqlDao.sql.stg
+++ b/tenant/src/main/resources/com/ning/billing/tenant/dao/TenantKVSqlDao.sql.stg
@@ -3,7 +3,7 @@ group TenantKVSqlDao;
tenantKVFields(prefix) ::= <<
<prefix>record_id,
- <prefix>id,
+ <prefix>tenant_record_id,
<prefix>t_key,
<prefix>t_value,
<prefix>created_date,
@@ -14,7 +14,7 @@ tenantKVFields(prefix) ::= <<
insertTenantKeyValue() ::= <<
INSERT INTO tenant_kvs (
- id
+ tenant_record_id
, t_key
, t_value
, created_date
@@ -22,7 +22,7 @@ insertTenantKeyValue() ::= <<
, updated_date
, updated_by
) VALUES (
- :id
+ :tenantRecordId
, :key
, :value
, :createdDate
@@ -37,7 +37,7 @@ getTenantValueForKey() ::= <<
SELECT <tenantKVFields()>
FROM tenant_kvs
WHERE
- id = :id AND t_key = :key
+ tenant_record_id = :tenantRecordId AND t_key = :key
;
>>
@@ -45,7 +45,7 @@ getTenantValueForKey() ::= <<
deleteTenantKey() ::= <<
DELETE FROM tenant_kvs
WHERE
- id = :id AND t_key = :key
+ tenant_record_id = :tenantRecordId AND t_key = :key
;
>>
diff --git a/tenant/src/main/resources/com/ning/billing/tenant/ddl.sql b/tenant/src/main/resources/com/ning/billing/tenant/ddl.sql
index ac9d885..a8a7911 100644
--- a/tenant/src/main/resources/com/ning/billing/tenant/ddl.sql
+++ b/tenant/src/main/resources/com/ning/billing/tenant/ddl.sql
@@ -19,14 +19,13 @@ CREATE UNIQUE INDEX tenants_api_key ON tenants(api_key);
DROP TABLE IF EXISTS tenant_kvs;
CREATE TABLE tenant_kvs (
record_id int(11) unsigned NOT NULL AUTO_INCREMENT,
- -- This is the tenant id, no id is generated as this is not a customer facing object
- id char(36) NOT NULL,
+ tenant_record_id int(11) unsigned default null,
t_key varchar(64) NOT NULL,
- t_value varchar(512) NOT NULL,
+ t_value varchar(1024) NOT NULL,
created_date datetime NOT NULL,
created_by varchar(50) NOT NULL,
updated_date datetime DEFAULT NULL,
updated_by varchar(50) DEFAULT NULL,
PRIMARY KEY(record_id)
) ENGINE=innodb;
-CREATE INDEX tenant_kvs_key ON tenant_kvs(id, t_key);
\ No newline at end of file
+CREATE INDEX tenant_kvs_key ON tenant_kvs(tenant_record_id, t_key);
\ No newline at end of file
diff --git a/tenant/src/test/java/com/ning/billing/tenant/dao/TestDefaultTenantDao.java b/tenant/src/test/java/com/ning/billing/tenant/dao/TestDefaultTenantDao.java
index 9a8cc58..f069f59 100644
--- a/tenant/src/test/java/com/ning/billing/tenant/dao/TestDefaultTenantDao.java
+++ b/tenant/src/test/java/com/ning/billing/tenant/dao/TestDefaultTenantDao.java
@@ -16,6 +16,7 @@
package com.ning.billing.tenant.dao;
+import java.util.List;
import java.util.UUID;
import org.apache.shiro.authc.AuthenticationInfo;
@@ -63,11 +64,18 @@ public class TestDefaultTenantDao extends TenantTestSuiteWithEmbeddedDb {
UUID.randomUUID().toString(), UUID.randomUUID().toString());
tenantDao.create(tenant, internalCallContext);
- tenantDao.addTenantKeyValue(tenant.getId(), "TheKey", "TheValue", internalCallContext);
+ tenantDao.addTenantKeyValue("TheKey", "TheValue", internalCallContext);
- final String value = tenantDao.getTenantValueForKey(tenant.getId(), "TheKey");
- Assert.assertEquals(value, "TheValue");
+ List<String> value = tenantDao.getTenantValueForKey("TheKey", internalCallContext);
+ Assert.assertEquals(value.size(), 1);
+ Assert.assertEquals(value.get(0), "TheValue");
- tenantDao.deleteTenantKey(tenant.getId(), "TheKey");
+ tenantDao.addTenantKeyValue("TheKey", "TheSecondValue", internalCallContext);
+ value = tenantDao.getTenantValueForKey("TheKey", internalCallContext);
+ Assert.assertEquals(value.size(), 2);
+
+ tenantDao.deleteTenantKey("TheKey", internalCallContext);
+ value = tenantDao.getTenantValueForKey("TheKey", internalCallContext);
+ Assert.assertEquals(value.size(), 0);
}
}
diff --git a/util/src/test/java/com/ning/billing/dbi/MysqlTestingHelper.java b/util/src/test/java/com/ning/billing/dbi/MysqlTestingHelper.java
index 6432a26..bcf65bc 100644
--- a/util/src/test/java/com/ning/billing/dbi/MysqlTestingHelper.java
+++ b/util/src/test/java/com/ning/billing/dbi/MysqlTestingHelper.java
@@ -70,7 +70,7 @@ public class MysqlTestingHelper {
socket = new ServerSocket(0);
port = socket.getLocalPort();
socket.close();
- } catch (IOException e) {
+ } catch (final IOException e) {
Assert.fail();
}
}
@@ -172,7 +172,7 @@ public class MysqlTestingHelper {
deleteRecursive(dbDir);
log.info("MySQLd stopped");
}
- } catch (Exception ex) {
+ } catch (final Exception ex) {
//fail silently
}
}
@@ -231,7 +231,7 @@ public class MysqlTestingHelper {
final String ddl;
try {
ddl = IOUtils.toString(Resources.getResource("com/ning/billing/" + pack + "/ddl.sql").openStream());
- } catch (IllegalArgumentException ignored) {
+ } catch (final IllegalArgumentException ignored) {
// The test doesn't have this module ddl in the classpath - that's fine
continue;
}
@@ -247,7 +247,7 @@ public class MysqlTestingHelper {
dbi.withHandle(new HandleCallback<Void>() {
@Override
public Void withHandle(final Handle handle) throws Exception {
- log.debug("Executing DDL script: " + ddl);
+ log.info("Executing DDL script: " + ddl);
handle.createScript(ddl).execute();
return null;
}