killbill-aplcache
Changes
account/src/main/java/com/ning/billing/account/api/user/DefaultAccountChangeNotification.java 5(+5 -0)
bin/db-helper 2(+1 -1)
bin/start-server 5(+3 -2)
entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionTransitionData.java 6(+6 -0)
invoice/src/main/java/com/ning/billing/invoice/api/user/DefaultInvoiceCreationNotification.java 7(+7 -0)
pom.xml 7(+7 -0)
server/pom.xml 6(+6 -0)
Details
diff --git a/account/src/main/java/com/ning/billing/account/api/user/DefaultAccountChangeNotification.java b/account/src/main/java/com/ning/billing/account/api/user/DefaultAccountChangeNotification.java
index 11a5a39..33e1e3a 100644
--- a/account/src/main/java/com/ning/billing/account/api/user/DefaultAccountChangeNotification.java
+++ b/account/src/main/java/com/ning/billing/account/api/user/DefaultAccountChangeNotification.java
@@ -102,4 +102,9 @@ public class DefaultAccountChangeNotification implements AccountChangeNotificati
inputList.add(new DefaultChangedField(key, oldData, newData));
}
}
+
+ @Override
+ public BusEventType getBusEventType() {
+ return BusEventType.ACCOUNT_CHANGE;
+ }
}
diff --git a/account/src/main/java/com/ning/billing/account/api/user/DefaultAccountCreationEvent.java b/account/src/main/java/com/ning/billing/account/api/user/DefaultAccountCreationEvent.java
index 91d9b82..19b76e5 100644
--- a/account/src/main/java/com/ning/billing/account/api/user/DefaultAccountCreationEvent.java
+++ b/account/src/main/java/com/ning/billing/account/api/user/DefaultAccountCreationEvent.java
@@ -19,6 +19,7 @@ package com.ning.billing.account.api.user;
import com.ning.billing.account.api.Account;
import com.ning.billing.account.api.AccountCreationNotification;
import com.ning.billing.account.api.AccountData;
+import com.ning.billing.util.bus.BusEvent.BusEventType;
import java.util.UUID;
@@ -40,4 +41,10 @@ public class DefaultAccountCreationEvent implements AccountCreationNotification
public AccountData getData() {
return data;
}
+
+ @Override
+ public BusEventType getBusEventType() {
+ return BusEventType.ACCOUNT_CREATE;
+ }
+
}
diff --git a/analytics/src/test/java/com/ning/billing/analytics/api/TestAnalyticsService.java b/analytics/src/test/java/com/ning/billing/analytics/api/TestAnalyticsService.java
index 495e985..99c68d6 100644
--- a/analytics/src/test/java/com/ning/billing/analytics/api/TestAnalyticsService.java
+++ b/analytics/src/test/java/com/ning/billing/analytics/api/TestAnalyticsService.java
@@ -190,8 +190,7 @@ public class TestAnalyticsService {
helper.initDb(paymentDdl);
helper.initDb(utilDdl);
- helper.cleanupTable("tag_definitions");
- helper.cleanupTable("accounts");
+ helper.cleanupAllTables();
}
private void createSubscriptionTransitionEvent(final Account account) throws EntitlementUserApiException {
@@ -289,6 +288,7 @@ public class TestAnalyticsService {
// Send events and wait for the async part...
bus.post(transition);
+
bus.post(accountCreationNotification);
Thread.sleep(1000);
diff --git a/api/src/main/java/com/ning/billing/payment/api/PaymentError.java b/api/src/main/java/com/ning/billing/payment/api/PaymentError.java
index 5541b01..d546e3f 100644
--- a/api/src/main/java/com/ning/billing/payment/api/PaymentError.java
+++ b/api/src/main/java/com/ning/billing/payment/api/PaymentError.java
@@ -17,10 +17,12 @@
package com.ning.billing.payment.api;
import java.util.UUID;
+import org.codehaus.jackson.annotate.JsonIgnore;
import org.codehaus.jackson.annotate.JsonTypeInfo;
import org.codehaus.jackson.annotate.JsonTypeInfo.Id;
import com.ning.billing.util.bus.BusEvent;
+import com.ning.billing.util.bus.BusEvent.BusEventType;
@JsonTypeInfo(use = Id.NAME, property = "error")
public class PaymentError implements BusEvent {
@@ -117,5 +119,12 @@ public class PaymentError implements BusEvent {
public String toString() {
return "PaymentError [type=" + type + ", message=" + message + ", accountId=" + accountId + ", invoiceId=" + invoiceId + "]";
}
+
+ @JsonIgnore
+ @Override
+ public BusEventType getBusEventType() {
+ return BusEventType.PAYMENT_ERROR;
+ }
+
}
diff --git a/api/src/main/java/com/ning/billing/payment/api/PaymentInfo.java b/api/src/main/java/com/ning/billing/payment/api/PaymentInfo.java
index e325d9a..ad0c516 100644
--- a/api/src/main/java/com/ning/billing/payment/api/PaymentInfo.java
+++ b/api/src/main/java/com/ning/billing/payment/api/PaymentInfo.java
@@ -19,12 +19,14 @@ package com.ning.billing.payment.api;
import java.math.BigDecimal;
import org.codehaus.jackson.annotate.JsonCreator;
+import org.codehaus.jackson.annotate.JsonIgnore;
import org.codehaus.jackson.annotate.JsonProperty;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import com.google.common.base.Objects;
import com.ning.billing.util.bus.BusEvent;
+import com.ning.billing.util.bus.BusEvent.BusEventType;
public class PaymentInfo implements BusEvent {
private final String paymentId;
@@ -348,4 +350,11 @@ public class PaymentInfo implements BusEvent {
private static long getUnixTimestamp(final DateTime dateTime) {
return dateTime.getMillis() / 1000;
}
+
+ @JsonIgnore
+ @Override
+ public BusEventType getBusEventType() {
+ return BusEventType.PAYMENT_INFO;
+ }
+
}
diff --git a/api/src/main/java/com/ning/billing/util/bus/BusEvent.java b/api/src/main/java/com/ning/billing/util/bus/BusEvent.java
index 481cb74..ef5bc04 100644
--- a/api/src/main/java/com/ning/billing/util/bus/BusEvent.java
+++ b/api/src/main/java/com/ning/billing/util/bus/BusEvent.java
@@ -17,5 +17,16 @@
package com.ning.billing.util.bus;
public interface BusEvent {
+
+ public enum BusEventType {
+ ACCOUNT_CREATE,
+ ACCOUNT_CHANGE,
+ SUBSCRIPTION_TRANSITION,
+ INVOICE_CREATION,
+ PAYMENT_INFO,
+ PAYMENT_ERROR
+ }
+
+ public BusEventType getBusEventType();
}
bin/db-helper 2(+1 -1)
diff --git a/bin/db-helper b/bin/db-helper
index 1d4a5b9..3bd86ae 100755
--- a/bin/db-helper
+++ b/bin/db-helper
@@ -37,7 +37,7 @@ CLEAN_FILE=
function usage() {
echo -n "./db_helper "
- echo -n " -a <create|clean>"
+ echo -n " -a <create|clean|dump>"
echo -n " -d database_name (default = killbill)"
echo -n " -u user_name (default = root)"
echo -n " -p password (default = root)"
bin/start-server 5(+3 -2)
diff --git a/bin/start-server b/bin/start-server
index bc60df8..ce254da 100755
--- a/bin/start-server
+++ b/bin/start-server
@@ -93,6 +93,7 @@ while getopts ":pswdh" options; do
done
if [ ! -z $START ]; then
- echo "coucouc"
start
-fi
\ No newline at end of file
+else
+ usage
+fi
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionTransitionData.java b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionTransitionData.java
index f03193b..18a1471 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionTransitionData.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionTransitionData.java
@@ -22,6 +22,8 @@ import com.ning.billing.entitlement.api.user.Subscription.SubscriptionState;
import com.ning.billing.entitlement.events.EntitlementEvent.EventType;
import com.ning.billing.entitlement.events.user.ApiEventType;
import com.ning.billing.entitlement.exceptions.EntitlementError;
+import com.ning.billing.util.bus.BusEvent.BusEventType;
+
import org.joda.time.DateTime;
import java.util.UUID;
@@ -186,4 +188,8 @@ public class SubscriptionTransitionData implements SubscriptionTransition {
+ ", nextPhase=" + ((nextPhase != null) ? nextPhase.getName() : null) + "]";
}
+ @Override
+ public BusEventType getBusEventType() {
+ return BusEventType.SUBSCRIPTION_TRANSITION;
+ }
}
diff --git a/invoice/src/main/java/com/ning/billing/invoice/api/user/DefaultInvoiceCreationNotification.java b/invoice/src/main/java/com/ning/billing/invoice/api/user/DefaultInvoiceCreationNotification.java
index 5c6785c..8156779 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/api/user/DefaultInvoiceCreationNotification.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/api/user/DefaultInvoiceCreationNotification.java
@@ -23,6 +23,7 @@ import org.joda.time.DateTime;
import com.ning.billing.catalog.api.Currency;
import com.ning.billing.invoice.api.InvoiceCreationNotification;
+import com.ning.billing.util.bus.BusEvent.BusEventType;
public class DefaultInvoiceCreationNotification implements InvoiceCreationNotification {
private final UUID invoiceId;
@@ -68,5 +69,11 @@ public class DefaultInvoiceCreationNotification implements InvoiceCreationNotifi
public String toString() {
return "DefaultInvoiceCreationNotification [invoiceId=" + invoiceId + ", accountId=" + accountId + ", amountOwed=" + amountOwed + ", currency=" + currency + ", invoiceCreationDate=" + invoiceCreationDate + "]";
}
+
+
+ @Override
+ public BusEventType getBusEventType() {
+ return BusEventType.INVOICE_CREATION;
+ }
}
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/BundleJson.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/BundleJson.java
index 226c365..12543cc 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/BundleJson.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/BundleJson.java
@@ -22,6 +22,8 @@ import org.codehaus.jackson.annotate.JsonCreator;
import org.codehaus.jackson.annotate.JsonProperty;
import org.codehaus.jackson.map.annotate.JsonView;
+import com.ning.billing.entitlement.api.user.SubscriptionBundle;
+
public class BundleJson {
@JsonView(BundleTimelineViews.Base.class)
@@ -63,4 +65,75 @@ public class BundleJson {
public List<SubscriptionJson> getSubscriptions() {
return subscriptions;
}
+
+ public BundleJson(SubscriptionBundle bundle) {
+ this.bundleId = bundle.getId().toString();
+ this.accountId = bundle.getAccountId().toString();
+ this.externalKey = bundle.getKey();
+ this.subscriptions = null;
+ }
+
+ public BundleJson() {
+ this.bundleId = null;
+ this.accountId = null;
+ this.externalKey = null;
+ this.subscriptions = null;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result
+ + ((accountId == null) ? 0 : accountId.hashCode());
+ result = prime * result
+ + ((bundleId == null) ? 0 : bundleId.hashCode());
+ result = prime * result
+ + ((externalKey == null) ? 0 : externalKey.hashCode());
+ result = prime * result
+ + ((subscriptions == null) ? 0 : subscriptions.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (equalsNoId(obj) == false) {
+ return false;
+ }
+ BundleJson other = (BundleJson) obj;
+ if (bundleId == null) {
+ if (other.bundleId != null)
+ return false;
+ } else if (!bundleId.equals(other.bundleId))
+ return false;
+ return true;
+ }
+
+ public boolean equalsNoId(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ BundleJson other = (BundleJson) obj;
+ if (accountId == null) {
+ if (other.accountId != null)
+ return false;
+ } else if (!accountId.equals(other.accountId))
+ return false;
+ if (externalKey == null) {
+ if (other.externalKey != null)
+ return false;
+ } else if (!externalKey.equals(other.externalKey))
+ return false;
+ if (subscriptions == null) {
+ if (other.subscriptions != null)
+ return false;
+ } else if (!subscriptions.equals(other.subscriptions))
+ return false;
+ return true;
+ }
+
+
}
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/SubscriptionJson.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/SubscriptionJson.java
index a08a305..20b222c 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/SubscriptionJson.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/SubscriptionJson.java
@@ -23,6 +23,8 @@ import org.codehaus.jackson.annotate.JsonProperty;
import org.codehaus.jackson.map.annotate.JsonView;
import org.joda.time.DateTime;
+import com.ning.billing.catalog.api.CatalogService;
+import com.ning.billing.entitlement.api.user.Subscription;
import com.ning.billing.util.clock.DefaultClock;
public class SubscriptionJson {
@@ -223,6 +225,31 @@ public class SubscriptionJson {
this.deletedEvents = deletedEvents;
this.newEvents = newEvents;
}
+
+ public SubscriptionJson() {
+ this.subscriptionId = null;
+ this.bundleId = null;
+ this.productName = null;
+ this.productCategory = null;
+ this.billingPeriod = null;
+ this.priceList = null;
+ this.events = null;
+ this.deletedEvents = null;
+ this.newEvents = null;
+ }
+
+ public SubscriptionJson(final Subscription data,
+ List<SubscriptionReadEventJson> events, List<SubscriptionDeletedEventJson> deletedEvents, List<SubscriptionNewEventJson> newEvents) {
+ this.subscriptionId = data.getId().toString();
+ this.bundleId = data.getBundleId().toString();
+ this.productName = data.getCurrentPlan().getProduct().getName();
+ this.productCategory = data.getCurrentPlan().getProduct().getCategory().toString();
+ this.billingPeriod = data.getCurrentPlan().getBillingPeriod().toString();
+ this.priceList = data.getCurrentPriceList();
+ this.events = events;
+ this.deletedEvents = deletedEvents;
+ this.newEvents = newEvents;
+ }
public String getSubscriptionId() {
return subscriptionId;
@@ -269,4 +296,75 @@ public class SubscriptionJson {
+ events + ", deletedEvents=" + deletedEvents + ", newEvents="
+ newEvents + "]";
}
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result
+ + ((billingPeriod == null) ? 0 : billingPeriod.hashCode());
+ result = prime * result
+ + ((bundleId == null) ? 0 : bundleId.hashCode());
+ result = prime * result
+ + ((priceList == null) ? 0 : priceList.hashCode());
+ result = prime * result
+ + ((productCategory == null) ? 0 : productCategory.hashCode());
+ result = prime * result
+ + ((productName == null) ? 0 : productName.hashCode());
+ result = prime * result
+ + ((subscriptionId == null) ? 0 : subscriptionId.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (equalsNoId(obj) == false) {
+ return false;
+ }
+ SubscriptionJson other = (SubscriptionJson) obj;
+ if (subscriptionId == null) {
+ if (other.subscriptionId != null)
+ return false;
+ } else if (!subscriptionId.equals(other.subscriptionId))
+ return false;
+ return true;
+ }
+
+ public boolean equalsNoId(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ SubscriptionJson other = (SubscriptionJson) obj;
+ if (billingPeriod == null) {
+ if (other.billingPeriod != null)
+ return false;
+ } else if (!billingPeriod.equals(other.billingPeriod))
+ return false;
+ if (bundleId == null) {
+ if (other.bundleId != null)
+ return false;
+ } else if (!bundleId.equals(other.bundleId))
+ return false;
+ if (priceList == null) {
+ if (other.priceList != null)
+ return false;
+ } else if (!priceList.equals(other.priceList))
+ return false;
+ if (productCategory == null) {
+ if (other.productCategory != null)
+ return false;
+ } else if (!productCategory.equals(other.productCategory))
+ return false;
+ if (productName == null) {
+ if (other.productName != null)
+ return false;
+ } else if (!productName.equals(other.productName))
+ return false;
+ return true;
+ }
+
+
}
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/AccountResource.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/AccountResource.java
index 7601229..c3d0ffa 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
@@ -19,6 +19,7 @@ package com.ning.billing.jaxrs.resources;
import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
import java.net.URI;
+import java.util.Collection;
import java.util.List;
import java.util.UUID;
@@ -35,11 +36,11 @@ import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.Response.Status;
-import org.codehaus.jackson.annotate.JsonCreator;
-import org.codehaus.jackson.annotate.JsonProperty;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.google.common.base.Function;
+import com.google.common.collect.Collections2;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import com.ning.billing.ErrorCode;
@@ -50,7 +51,9 @@ import com.ning.billing.account.api.AccountUserApi;
import com.ning.billing.entitlement.api.user.EntitlementUserApi;
import com.ning.billing.entitlement.api.user.SubscriptionBundle;
import com.ning.billing.jaxrs.json.AccountJson;
+import com.ning.billing.jaxrs.json.BundleJson;
import com.ning.billing.jaxrs.util.Context;
+import com.ning.billing.jaxrs.util.JaxrsUriBuilder;
@Singleton
@@ -60,12 +63,14 @@ public class AccountResource implements BaseJaxrsResource {
private static final Logger log = LoggerFactory.getLogger(AccountResource.class);
private final AccountUserApi accountApi;
- final EntitlementUserApi entitlementApi;
+ private final EntitlementUserApi entitlementApi;
private final Context context;
+ private final JaxrsUriBuilder uriBuilder;
@Inject
- public AccountResource(final AccountUserApi accountApi, final EntitlementUserApi entitlementApi, final Context context) {
- this.accountApi = accountApi;
+ public AccountResource(final JaxrsUriBuilder uriBuilder, final AccountUserApi accountApi, final EntitlementUserApi entitlementApi, final Context context) {
+ this.uriBuilder = uriBuilder;
+ this.accountApi = accountApi;
this.entitlementApi = entitlementApi;
this.context = context;
}
@@ -76,7 +81,7 @@ public class AccountResource implements BaseJaxrsResource {
public Response getAccount(@PathParam("accountId") String accountId) {
Account account = accountApi.getAccountById(UUID.fromString(accountId));
if (account == null) {
- return Response.status(Status.NO_CONTENT).build();
+ return Response.status(Status.NO_CONTENT).build();
}
AccountJson json = new AccountJson(account);
return Response.status(Status.OK).entity(json).build();
@@ -86,12 +91,20 @@ public class AccountResource implements BaseJaxrsResource {
@Path("/{accountId:" + UUID_PATTERN + "}/" + BUNDLES)
@Produces(APPLICATION_JSON)
public Response getAccountBundles(@PathParam("accountId") String accountId) {
+
UUID uuid = UUID.fromString(accountId);
+ Account account = accountApi.getAccountById(uuid);
+ if (account == null) {
+ return Response.status(Status.NO_CONTENT).build();
+ }
List<SubscriptionBundle> bundles = entitlementApi.getBundlesForAccount(uuid);
- // STEPH should we fetch account first to make sure id exists or what's the deal here
- //
- String json = null;
- return Response.status(Status.OK).entity(json).build();
+ Collection<BundleJson> result = Collections2.transform(bundles, new Function<SubscriptionBundle, BundleJson>() {
+ @Override
+ public BundleJson apply(SubscriptionBundle input) {
+ return new BundleJson(input);
+ }
+ });
+ return Response.status(Status.OK).entity(result).build();
}
@@ -120,12 +133,7 @@ public class AccountResource implements BaseJaxrsResource {
AccountData data = json.toAccountData();
final Account account = accountApi.createAccount(data, null, null, context.getContext());
URI uri = UriBuilder.fromPath(account.getId().toString()).build();
- Response.ResponseBuilder ri = Response.created(uri);
- return ri.entity(new Object() {
- public URI getUri() {
- return UriBuilder.fromResource(AccountResource.class).path(AccountResource.class, "getAccount").build(account.getId());
- }
- }).build();
+ return uriBuilder.buildResponse(AccountResource.class, "getAccount", account.getId());
} catch (AccountApiException e) {
log.info(String.format("Failed to create account %s", json), e);
return Response.status(Status.BAD_REQUEST).build();
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/BaseJaxrsResource.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/BaseJaxrsResource.java
index 9eb01eb..02d9f86 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/BaseJaxrsResource.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/BaseJaxrsResource.java
@@ -29,11 +29,16 @@ public interface BaseJaxrsResource {
* Query parameters
*/
public static final String QUERY_EXTERNAL_KEY = "external_key";
+ public static final String QUERY_REQUESTED_DT = "requested_date";
public static final String ACCOUNTS = "accounts";
public static final String ACCOUNTS_PATH = API_PREFIX + API_VERSION + "/" + ACCOUNTS;
public static final String BUNDLES = "bundles";
+ public static final String BUNDLES_PATH = API_PREFIX + API_VERSION + "/" + BUNDLES;
+
+ public static final String SUBSCRIPTIONS = "subscriptions";
+ public static final String SUBSCRIPTIONS_PATH = API_PREFIX + API_VERSION + "/" + SUBSCRIPTIONS;
}
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/BundleResource.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/BundleResource.java
index ba9405e..90c9e81 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/BundleResource.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/BundleResource.java
@@ -18,6 +18,10 @@ package com.ning.billing.jaxrs.resources;
import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
+import java.util.Collection;
+import java.util.List;
+import java.util.UUID;
+
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
@@ -28,29 +32,91 @@ import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Function;
+import com.google.common.collect.Collections2;
+import com.google.inject.Inject;
+import com.ning.billing.entitlement.api.user.EntitlementUserApi;
+import com.ning.billing.entitlement.api.user.EntitlementUserApiException;
+import com.ning.billing.entitlement.api.user.Subscription;
+import com.ning.billing.entitlement.api.user.SubscriptionBundle;
import com.ning.billing.jaxrs.json.BundleJson;
+import com.ning.billing.jaxrs.json.SubscriptionJson;
+import com.ning.billing.jaxrs.util.Context;
+import com.ning.billing.jaxrs.util.JaxrsUriBuilder;
+
+@Path(BaseJaxrsResource.BUNDLES_PATH)
+public class BundleResource implements BaseJaxrsResource {
+
+ private static final Logger log = LoggerFactory.getLogger(BundleResource.class);
+
+ private final EntitlementUserApi entitlementApi;
+ private final Context context;
+ private final JaxrsUriBuilder uriBuilder;
+
+ @Inject
+ public BundleResource(final JaxrsUriBuilder uriBuilder, final EntitlementUserApi entitlementApi, final Context context) {
+ this.uriBuilder = uriBuilder;
+ this.entitlementApi = entitlementApi;
+ this.context = context;
+ }
+
+ @GET
+ @Path("/{bundleId:" + UUID_PATTERN + "}")
+ @Produces(APPLICATION_JSON)
+ public Response getBundle(@PathParam("bundleId") final String bundleId) {
+ SubscriptionBundle bundle = entitlementApi.getBundleFromId(UUID.fromString(bundleId));
+ if (bundle == null) {
+ return Response.status(Status.NO_CONTENT).build();
+ }
+ BundleJson json = new BundleJson(bundle);
+ return Response.status(Status.OK).entity(json).build();
+ }
-@Path("/1.0/bundle")
-public class BundleResource {
-
- @GET
- @Path("/{bundleId:\\\\w+-\\\\w+-\\\\w+-\\\\w+-\\\\w+}")
- @Produces(APPLICATION_JSON)
- public Response getBundle(@PathParam("bundleId") String bundleId) {
- return Response.status(Status.INTERNAL_SERVER_ERROR).build();
- }
-
- @GET
- @Produces(APPLICATION_JSON)
- public Response getBundleByKey(@QueryParam("externalKey") String externalKey) {
- return Response.status(Status.INTERNAL_SERVER_ERROR).build();
- }
-
- @POST
- @Consumes(APPLICATION_JSON)
- @Produces(APPLICATION_JSON)
- public Response createBundle(BundleJson bundle) {
- return Response.status(Status.INTERNAL_SERVER_ERROR).build();
- }
+ @GET
+ @Produces(APPLICATION_JSON)
+ public Response getBundleByKey(@QueryParam(QUERY_EXTERNAL_KEY) final String externalKey) {
+ SubscriptionBundle bundle = entitlementApi.getBundleForKey(externalKey);
+ if (bundle == null) {
+ return Response.status(Status.NO_CONTENT).build();
+ }
+ BundleJson json = new BundleJson(bundle);
+ return Response.status(Status.OK).entity(json).build();
+ }
+ @POST
+ @Consumes(APPLICATION_JSON)
+ @Produces(APPLICATION_JSON)
+ public Response createBundle(final BundleJson json) {
+ try {
+ UUID accountId = UUID.fromString(json.getAccountId());
+ final SubscriptionBundle bundle = entitlementApi.createBundleForAccount(accountId, json.getExternalKey(), context.getContext());
+ return uriBuilder.buildResponse(BundleResource.class, "getBundle", bundle.getId());
+ } catch (EntitlementUserApiException e) {
+ log.info(String.format("Failed to create bundle %s", json), e);
+ return Response.status(Status.BAD_REQUEST).build();
+ }
+ }
+
+ @GET
+ @Path("/{bundleId:" + UUID_PATTERN + "}/" + SUBSCRIPTIONS)
+ @Produces(APPLICATION_JSON)
+ public Response getBundleSubscriptions(@PathParam("bundleId") final String bundleId) {
+
+ UUID uuid = UUID.fromString(bundleId);
+ SubscriptionBundle bundle = entitlementApi.getBundleFromId(uuid);
+ if (bundle == null) {
+ return Response.status(Status.NO_CONTENT).build();
+ }
+ List<Subscription> bundles = entitlementApi.getSubscriptionsForBundle(uuid);
+ Collection<SubscriptionJson> result = Collections2.transform(bundles, new Function<Subscription, SubscriptionJson>() {
+ @Override
+ public SubscriptionJson apply(Subscription input) {
+ return new SubscriptionJson(input, null, null, null);
+ }
+ });
+ return Response.status(Status.OK).entity(result).build();
+ }
}
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/SubscriptionResource.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/SubscriptionResource.java
index 943ef50..e4b5893 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/SubscriptionResource.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/SubscriptionResource.java
@@ -18,6 +18,8 @@ package com.ning.billing.jaxrs.resources;
import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
+import java.util.UUID;
+
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
@@ -31,50 +33,141 @@ import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import org.joda.time.DateTime;
+import org.joda.time.format.DateTimeFormatter;
+import org.joda.time.format.ISODateTimeFormat;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import com.google.inject.Inject;
+import com.ning.billing.catalog.api.BillingPeriod;
+import com.ning.billing.catalog.api.PlanPhaseSpecifier;
+import com.ning.billing.catalog.api.ProductCategory;
+import com.ning.billing.entitlement.api.user.EntitlementUserApi;
+import com.ning.billing.entitlement.api.user.EntitlementUserApiException;
+import com.ning.billing.entitlement.api.user.Subscription;
import com.ning.billing.entitlement.api.user.Subscription.SubscriptionState;
import com.ning.billing.jaxrs.json.SubscriptionJson;
+import com.ning.billing.jaxrs.util.Context;
+import com.ning.billing.jaxrs.util.JaxrsUriBuilder;
+import com.ning.billing.util.clock.Clock;
+
+@Path(BaseJaxrsResource.SUBSCRIPTIONS_PATH)
+public class SubscriptionResource implements BaseJaxrsResource{
+
+ private static final Logger log = LoggerFactory.getLogger(SubscriptionResource.class);
+
+ private final DateTimeFormatter DATE_TIME_FORMATTER = ISODateTimeFormat.dateTime();
+
+ private final EntitlementUserApi entitlementApi;
+ private final Context context;
+ private final JaxrsUriBuilder uriBuilder;
+ private final Clock clock;
+
+ @Inject
+ public SubscriptionResource(final JaxrsUriBuilder uriBuilder, final EntitlementUserApi entitlementApi, final Clock clock, final Context context) {
+ this.uriBuilder = uriBuilder;
+ this.entitlementApi = entitlementApi;
+ this.context = context;
+ this.clock = clock;
+ }
+
+ @GET
+ @Path("/{subscriptionId:" + UUID_PATTERN + "}")
+ @Produces(APPLICATION_JSON)
+ public Response getSubscription(@PathParam("subscriptionId") final String subscriptionId) {
+
+ UUID uuid = UUID.fromString(subscriptionId);
+ Subscription subscription = entitlementApi.getSubscriptionFromId(uuid);
+ if (subscription == null) {
+ return Response.status(Status.NO_CONTENT).build();
+ }
+ SubscriptionJson json = new SubscriptionJson(subscription, null, null, null);
+ return Response.status(Status.OK).entity(json).build();
+ }
+
+ @POST
+ @Consumes(APPLICATION_JSON)
+ @Produces(APPLICATION_JSON)
+ public Response createSubscription(SubscriptionJson subscription,
+ @QueryParam(QUERY_REQUESTED_DT) String requestedDate) {
+
+ try {
+ DateTime inputDate = (requestedDate != null) ? DATE_TIME_FORMATTER.parseDateTime(requestedDate) : null;
+ UUID uuid = UUID.fromString(subscription.getBundleId());
+
+ PlanPhaseSpecifier spec = new PlanPhaseSpecifier(subscription.getProductName(),
+ ProductCategory.valueOf(subscription.getProductCategory()),
+ BillingPeriod.valueOf(subscription.getBillingPeriod()), subscription.getPriceList(), null);
+ Subscription created = entitlementApi.createSubscription(uuid, spec, inputDate, context.getContext());
+ return uriBuilder.buildResponse(SubscriptionResource.class, "getSubscription", created.getId());
+
+ } catch (EntitlementUserApiException e) {
+ log.info(String.format("Failed to create subscription %s", subscription), e);
+ return Response.status(Status.BAD_REQUEST).build();
+ }
+ }
+
+ @PUT
+ @Produces(APPLICATION_JSON)
+ @Consumes(APPLICATION_JSON)
+ @Path("/{subscriptionId:" + UUID_PATTERN + "}")
+ public Response changeSubscriptionPlan(SubscriptionJson subscription,
+ @PathParam("subscriptionId") String subscriptionId,
+ @QueryParam(QUERY_REQUESTED_DT) String requestedDate) {
+
+ try {
+ UUID uuid = UUID.fromString(subscriptionId);
+ Subscription current = entitlementApi.getSubscriptionFromId(uuid);
+ if (current == null) {
+ return Response.status(Status.NO_CONTENT).build();
+ }
+ DateTime inputDate = (requestedDate != null) ? DATE_TIME_FORMATTER.parseDateTime(requestedDate) : null;
+ current.changePlan(subscription.getProductName(), BillingPeriod.valueOf(subscription.getBillingPeriod()), subscription.getPriceList(), inputDate, context.getContext());
+
+ return getSubscription(subscriptionId);
+ } catch (EntitlementUserApiException e) {
+ log.info(String.format("Failed to change plan for subscription %s", subscription), e);
+ return Response.status(Status.BAD_REQUEST).build();
+ }
+ }
+
+ @PUT
+ @Path("/{subscriptionId:" + UUID_PATTERN + "}/uncancel")
+ @Produces(APPLICATION_JSON)
+ public Response uncancelSubscriptionPlan(@PathParam("subscriptionId") String subscriptionId) {
+ try {
+ UUID uuid = UUID.fromString(subscriptionId);
+ Subscription current = entitlementApi.getSubscriptionFromId(uuid);
+ if (current == null) {
+ return Response.status(Status.NO_CONTENT).build();
+ }
+ current.uncancel(context.getContext());
+ return Response.status(Status.OK).build();
+ } catch (EntitlementUserApiException e) {
+ log.info(String.format("Failed to uncancel plan for subscription %s", subscriptionId), e);
+ return Response.status(Status.BAD_REQUEST).build();
+ }
+ }
+
+ @DELETE
+ @Path("/{subscriptionId:" + UUID_PATTERN + "}")
+ @Produces(APPLICATION_JSON)
+ public Response cancelSubscriptionPlan(@PathParam("subscriptionId") String subscriptionId,
+ @QueryParam(QUERY_REQUESTED_DT) String requestedDate) {
-@Path("/1.0/subscription")
-public class SubscriptionResource {
-
- @GET
- @Path("/{subscriptionId:\\w+-\\w+-\\w+-\\w+-\\w+}")
- @Produces(APPLICATION_JSON)
- public Response getSubscription(@PathParam("subscriptionId") String subscriptionId) {
- return Response.status(Status.INTERNAL_SERVER_ERROR).build();
- }
-
- @POST
- @Consumes(APPLICATION_JSON)
- @Produces(APPLICATION_JSON)
- public Response createSubscription(SubscriptionJson subscription,
- @QueryParam("requestedDate") String requestedDate) {
- return Response.status(Status.INTERNAL_SERVER_ERROR).build();
- }
-
- @PUT
- @Produces(APPLICATION_JSON)
- @Consumes(APPLICATION_JSON)
- @Path("/{subscriptionId:\\w+-\\w+-\\w+-\\w+-\\w+}")
- public Response changeSubscriptionPlan(SubscriptionJson subscription,
- @PathParam("subscriptionId") String subscriptionId,
- @QueryParam("requestedDate") String requestedDate) {
- return Response.status(Status.INTERNAL_SERVER_ERROR).build();
- }
-
- @PUT
- @Path("/{subscriptionId:\\w+-\\w+-\\w+-\\w+-\\w+}/uncancel")
- @Produces(APPLICATION_JSON)
- public Response uncancelSubscriptionPlan(@PathParam("subscriptionId") String subscriptionId) {
- return Response.status(Status.INTERNAL_SERVER_ERROR).build();
- }
-
- @DELETE
- @Path("/{subscriptionId:\\w+-\\w+-\\w+-\\w+-\\w+}")
- @Produces(APPLICATION_JSON)
- public Response cancelSubscriptionPlan(@PathParam("subscriptionId") String subscriptionId,
- @QueryParam("requestedDate") String requestedDate) {
- return Response.status(Status.INTERNAL_SERVER_ERROR).build();
- }
+ try {
+ UUID uuid = UUID.fromString(subscriptionId);
+ Subscription current = entitlementApi.getSubscriptionFromId(uuid);
+ if (current == null) {
+ return Response.status(Status.NO_CONTENT).build();
+ }
+ DateTime inputDate = (requestedDate != null) ? DATE_TIME_FORMATTER.parseDateTime(requestedDate) : null;
+ current.cancel(inputDate, false, context.getContext());
+ return Response.status(Status.OK).build();
+
+ } catch (EntitlementUserApiException e) {
+ log.info(String.format("Failed to cancel plan for subscription %s", subscriptionId), e);
+ return Response.status(Status.BAD_REQUEST).build();
+ }
+ }
}
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/util/JaxrsUriBuilder.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/util/JaxrsUriBuilder.java
new file mode 100644
index 0000000..a38a9fe
--- /dev/null
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/util/JaxrsUriBuilder.java
@@ -0,0 +1,39 @@
+/*
+ * 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.util;
+
+import java.net.URI;
+import java.util.UUID;
+
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriBuilder;
+
+import com.ning.billing.jaxrs.resources.BaseJaxrsResource;
+
+public class JaxrsUriBuilder {
+
+
+ public Response buildResponse(final Class<? extends BaseJaxrsResource> theClass, final String getMethodName, final UUID objectId) {
+ URI uri = UriBuilder.fromPath(objectId.toString()).build();
+ Response.ResponseBuilder ri = Response.created(uri);
+ return ri.entity(new Object() {
+ @SuppressWarnings(value = "all")
+ public URI getUri() {
+ return UriBuilder.fromResource(theClass).path(theClass, getMethodName).build(objectId);
+ }
+ }).build();
+ }
+}
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 e7e8b1e..153c63b 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
@@ -214,7 +214,7 @@ public class DefaultPaymentApi implements PaymentApi {
PaymentInfo paymentInfo = null;
if (paymentOrError.isLeft()) {
- String error = StringUtils.substring(paymentOrError.getLeft().getMessage() + paymentOrError.getLeft().getType(), 0, 100);
+ String error = StringUtils.substring(paymentOrError.getLeft().getMessage() + paymentOrError.getLeft().getBusEventType(), 0, 100);
log.info("Could not process a payment for " + paymentAttempt + " error was " + error);
scheduleRetry(paymentAttempt, error);
diff --git a/payment/src/test/java/com/ning/billing/payment/util/TestSyncWaitOnEventBus.java b/payment/src/test/java/com/ning/billing/payment/util/TestSyncWaitOnEventBus.java
index 0e76771..4fa635e 100644
--- a/payment/src/test/java/com/ning/billing/payment/util/TestSyncWaitOnEventBus.java
+++ b/payment/src/test/java/com/ning/billing/payment/util/TestSyncWaitOnEventBus.java
@@ -49,6 +49,11 @@ public class TestSyncWaitOnEventBus {
public String getMsg() {
return msg;
}
+
+ @Override
+ public BusEventType getBusEventType() {
+ return null;
+ }
}
private static final class TestResponse implements EventBusResponse<UUID> {
@@ -68,6 +73,11 @@ public class TestSyncWaitOnEventBus {
public String getMsg() {
return msg;
}
+
+ @Override
+ public BusEventType getBusEventType() {
+ return null;
+ }
}
private Bus eventBus;
pom.xml 7(+7 -0)
diff --git a/pom.xml b/pom.xml
index 8844cbc..b50bc5f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -64,6 +64,13 @@
</dependency>
<dependency>
<groupId>com.ning.billing</groupId>
+ <artifactId>killbill-beatrix</artifactId>
+ <version>${project.version}</version>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.ning.billing</groupId>
<artifactId>killbill-analytics</artifactId>
<version>${project.version}</version>
</dependency>
server/pom.xml 6(+6 -0)
diff --git a/server/pom.xml b/server/pom.xml
index a624843..6280399 100644
--- a/server/pom.xml
+++ b/server/pom.xml
@@ -250,6 +250,12 @@
<type>test-jar</type>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>com.ning.billing</groupId>
+ <artifactId>killbill-beatrix</artifactId>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-mxj</artifactId>
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 51091e5..424c10f 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
@@ -22,6 +22,7 @@ import com.ning.billing.server.config.KillbillServerConfig;
import com.ning.billing.server.healthchecks.KillbillHealthcheck;
import com.ning.billing.server.modules.KillbillServerModule;
import com.ning.billing.util.bus.Bus;
+import com.ning.billing.util.bus.BusEvent;
import com.ning.billing.util.bus.BusService;
import com.ning.jetty.base.modules.ServerModuleBuilder;
import com.ning.jetty.core.listeners.SetupServer;
@@ -127,7 +128,7 @@ public class KillbillGuiceListener extends SetupServer
* IRS event handler for killbill entitlement events
*/
@Subscribe
- public void handleEntitlementevents(SubscriptionTransition event)
+ public void handleEntitlementevents(BusEvent event)
{
logger.info("Killbill entitlement event {}", event.toString());
}
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 902f69e..f1fd9a8 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
@@ -64,6 +64,10 @@ public class KillbillServerModule extends AbstractModule
bind(PaymentResource.class).asEagerSingleton();
}
+ protected void installClock() {
+ install(new ClockModule());
+ }
+
protected void installKillbillModules() {
install(new FieldStoreModule());
install(new TagStoreModule());
@@ -77,6 +81,6 @@ public class KillbillServerModule extends AbstractModule
install(new AnalyticsModule());
install(new PaymentModule());
install(new BeatrixModule());
- install(new ClockModule());
+ installClock();
}
}
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 2b597df..4f0a4b2 100644
--- a/server/src/test/java/com/ning/billing/jaxrs/TestAccount.java
+++ b/server/src/test/java/com/ning/billing/jaxrs/TestAccount.java
@@ -42,30 +42,16 @@ public class TestAccount extends TestJaxrsBase {
@Test(groups="slow", enabled=true)
public void testAccountOk() throws Exception {
- AccountJson input = getAccountJson("xoxo", "shdgfhwe", "xoxo@yahoo.com");
- String baseJson = mapper.writeValueAsString(input);
- Response response = doPost(BaseJaxrsResource.ACCOUNTS_PATH, baseJson, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
- Assert.assertEquals(response.getStatusCode(), Status.CREATED.getStatusCode());
-
- String location = response.getHeader("Location");
- Assert.assertNotNull(location);
-
- // Retrieves by Id based on Location returned
- response = doGetWithUrl(location, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
- Assert.assertEquals(response.getStatusCode(), Status.OK.getStatusCode());
-
- baseJson = response.getResponseBody();
- AccountJson objFromJson = mapper.readValue(baseJson, AccountJson.class);
- Assert.assertTrue(objFromJson.equalsNoId(input));
-
+ AccountJson input = createAccount("xoxo", "shdgfhwe", "xoxo@yahoo.com");
+
// Retrieves by external key
Map<String, String> queryParams = new HashMap<String, String>();
queryParams.put(BaseJaxrsResource.QUERY_EXTERNAL_KEY, "shdgfhwe");
- response = doGet(BaseJaxrsResource.ACCOUNTS_PATH, queryParams, DEFAULT_HTTP_TIMEOUT_SEC);
+ Response response = doGet(BaseJaxrsResource.ACCOUNTS_PATH, queryParams, DEFAULT_HTTP_TIMEOUT_SEC);
Assert.assertEquals(response.getStatusCode(), Status.OK.getStatusCode());
- baseJson = response.getResponseBody();
- objFromJson = mapper.readValue(baseJson, AccountJson.class);
- Assert.assertTrue(objFromJson.equalsNoId(input));
+ String baseJson = response.getResponseBody();
+ AccountJson objFromJson = mapper.readValue(baseJson, AccountJson.class);
+ Assert.assertTrue(objFromJson.equals(input));
// Update Account
AccountJson newInput = new AccountJson(objFromJson.getAcountId(),
@@ -82,7 +68,7 @@ public class TestAccount extends TestJaxrsBase {
@Test(groups="slow", enabled=true)
public void testUpdateNonExistentAccount() throws Exception {
- AccountJson input = getAccountJson("xoxo", "shdgfhwe", "xoxo@yahoo.com");
+ AccountJson input = getAccountJson("xoxo", "shghaahwe", "xoxo@yahoo.com");
String baseJson = mapper.writeValueAsString(input);
final String uri = BaseJaxrsResource.ACCOUNTS_PATH + "/" + input.getAcountId();
Response response = doPut(uri, baseJson, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
diff --git a/server/src/test/java/com/ning/billing/jaxrs/TestBundle.java b/server/src/test/java/com/ning/billing/jaxrs/TestBundle.java
new file mode 100644
index 0000000..d340ab8
--- /dev/null
+++ b/server/src/test/java/com/ning/billing/jaxrs/TestBundle.java
@@ -0,0 +1,116 @@
+/*
+ * 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.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.ws.rs.core.Response.Status;
+
+import org.codehaus.jackson.type.TypeReference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.ning.billing.jaxrs.json.AccountJson;
+import com.ning.billing.jaxrs.json.BundleJson;
+import com.ning.billing.jaxrs.resources.BaseJaxrsResource;
+import com.ning.http.client.Response;
+
+public class TestBundle extends TestJaxrsBase {
+
+ private static final Logger log = LoggerFactory.getLogger(TestBundle.class);
+
+
+
+ @Test(groups="slow", enabled=true)
+ public void testBundleOk() throws Exception {
+
+ AccountJson accountJson = createAccount("xlxl", "shdgfhkkl", "xlxl@yahoo.com");
+ BundleJson bundleJson = createBundle(accountJson.getAcountId(), "12345");
+
+ // Retrieves by external key
+ Map<String, String> queryParams = new HashMap<String, String>();
+ queryParams.put(BaseJaxrsResource.QUERY_EXTERNAL_KEY, "12345");
+ Response response = doGet(BaseJaxrsResource.BUNDLES_PATH, queryParams, DEFAULT_HTTP_TIMEOUT_SEC);
+ Assert.assertEquals(response.getStatusCode(), Status.OK.getStatusCode());
+ String baseJson = response.getResponseBody();
+ BundleJson objFromJson = mapper.readValue(baseJson, BundleJson.class);
+ Assert.assertTrue(objFromJson.equals(bundleJson));
+ }
+
+
+ @Test(groups="slow", enabled=true)
+ public void testBundleFromAccount() throws Exception {
+
+ AccountJson accountJson = createAccount("xaxa", "saagfhkkl", "xaxa@yahoo.com");
+ BundleJson bundleJson1 = createBundle(accountJson.getAcountId(), "156567");
+ BundleJson bundleJson2 = createBundle(accountJson.getAcountId(), "265658");
+
+ String uri = BaseJaxrsResource.ACCOUNTS_PATH + "/" + accountJson.getAcountId().toString() + "/" + BaseJaxrsResource.BUNDLES;
+ Response response = doGet(uri, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
+ Assert.assertEquals(response.getStatusCode(), Status.OK.getStatusCode());
+ String baseJson = response.getResponseBody();
+ List<BundleJson> objFromJson = mapper.readValue(baseJson, new TypeReference<List<BundleJson>>() {});
+
+ Collections.sort(objFromJson, new Comparator<BundleJson>() {
+ @Override
+ public int compare(BundleJson o1, BundleJson o2) {
+ return o1.getExternalKey().compareTo(o2.getExternalKey());
+ }
+ });
+ Assert.assertEquals(objFromJson.get(0), bundleJson1);
+ Assert.assertEquals(objFromJson.get(1), bundleJson2);
+ }
+
+ @Test(groups="slow", enabled=true)
+ public void testBundleNonExistent() throws Exception {
+ AccountJson accountJson = createAccount("dfdf", "dfdfgfhkkl", "dfdf@yahoo.com");
+
+ String uri = BaseJaxrsResource.BUNDLES_PATH + "/99999999-b103-42f3-8b6e-dd244f1d0747";
+ Response response = doGet(uri, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
+ Assert.assertEquals(response.getStatusCode(), Status.NO_CONTENT.getStatusCode());
+
+
+ // Retrieves by external key
+ Map<String, String> queryParams = new HashMap<String, String>();
+ queryParams.put(BaseJaxrsResource.QUERY_EXTERNAL_KEY, "56566");
+ response = doGet(BaseJaxrsResource.BUNDLES_PATH, queryParams, DEFAULT_HTTP_TIMEOUT_SEC);
+ Assert.assertEquals(response.getStatusCode(), Status.NO_CONTENT.getStatusCode());
+
+
+ uri = BaseJaxrsResource.ACCOUNTS_PATH + "/" + accountJson.getAcountId().toString() + "/" + BaseJaxrsResource.BUNDLES;
+ response = doGet(uri, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
+ Assert.assertEquals(response.getStatusCode(), Status.OK.getStatusCode());
+ String baseJson = response.getResponseBody();
+ List<BundleJson> objFromJson = mapper.readValue(baseJson, new TypeReference<List<BundleJson>>() {});
+ Assert.assertNotNull(objFromJson);
+ Assert.assertEquals(objFromJson.size(), 0);
+ }
+
+ @Test(groups="slow", enabled=true)
+ public void testAppNonExistent() throws Exception {
+ String uri = BaseJaxrsResource.ACCOUNTS_PATH + "/99999999-b103-42f3-8b6e-dd244f1d0747/" + BaseJaxrsResource.BUNDLES;
+ Response response = doGet(uri, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
+ Assert.assertEquals(response.getStatusCode(), Status.NO_CONTENT.getStatusCode());
+ }
+
+
+}
diff --git a/server/src/test/java/com/ning/billing/jaxrs/TestJaxrsBase.java b/server/src/test/java/com/ning/billing/jaxrs/TestJaxrsBase.java
index 4db4a3b..ec2b3ea 100644
--- a/server/src/test/java/com/ning/billing/jaxrs/TestJaxrsBase.java
+++ b/server/src/test/java/com/ning/billing/jaxrs/TestJaxrsBase.java
@@ -28,6 +28,8 @@ import java.util.Map.Entry;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
+import javax.ws.rs.core.Response.Status;
+
import org.codehaus.jackson.map.ObjectMapper;
import org.eclipse.jetty.servlet.FilterHolder;
import org.skife.config.ConfigurationObjectFactory;
@@ -36,16 +38,24 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testng.Assert;
import org.testng.annotations.AfterClass;
-import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.BeforeSuite;
import com.google.inject.Injector;
import com.google.inject.Module;
+import com.ning.billing.beatrix.integration.TestBusHandler;
+import com.ning.billing.catalog.api.PriceListSet;
import com.ning.billing.dbi.DBIProvider;
import com.ning.billing.dbi.DbiConfig;
import com.ning.billing.dbi.MysqlTestingHelper;
import com.ning.billing.jaxrs.json.AccountJson;
+import com.ning.billing.jaxrs.json.BundleJson;
+import com.ning.billing.jaxrs.json.SubscriptionJson;
+import com.ning.billing.jaxrs.resources.BaseJaxrsResource;
import com.ning.billing.server.listeners.KillbillGuiceListener;
import com.ning.billing.server.modules.KillbillServerModule;
+import com.ning.billing.util.clock.Clock;
+import com.ning.billing.util.clock.ClockMock;
import com.ning.http.client.AsyncCompletionHandler;
import com.ning.http.client.AsyncHttpClient;
import com.ning.http.client.AsyncHttpClient.BoundRequestBuilder;
@@ -71,7 +81,8 @@ public class TestJaxrsBase {
protected CoreConfig config;
protected AsyncHttpClient httpClient;
protected ObjectMapper mapper;
-
+ protected ClockMock clock;
+ protected TestBusHandler busHandler;
public static void loadSystemPropertiesFromClasspath(final String resource) {
final URL url = TestJaxrsBase.class.getResource(resource);
@@ -99,6 +110,11 @@ public class TestJaxrsBase {
public static class TestKillbillServerModule extends KillbillServerModule {
@Override
+ protected void installClock() {
+ bind(Clock.class).to(ClockMock.class).asEagerSingleton();
+ }
+
+ @Override
protected void configureDao() {
final MysqlTestingHelper helper = new MysqlTestingHelper();
bind(MysqlTestingHelper.class).toInstance(helper);
@@ -113,9 +129,13 @@ public class TestJaxrsBase {
}
}
-
+ @BeforeMethod(groups="slow")
+ public void cleanupTables() {
+ helper.cleanupAllTables();
+ busHandler.reset();
+ }
- @BeforeClass(groups="slow")
+ @BeforeSuite(groups="slow")
public void setup() throws Exception {
loadSystemPropertiesFromClasspath("/killbill.properties");
@@ -137,9 +157,10 @@ public class TestJaxrsBase {
server.start();
Injector injector = ((TestKillbillGuiceListener) eventListener).getTheInjector();
-
helper = injector.getInstance(MysqlTestingHelper.class);
- helper.cleanupAllTables();
+ clock = (ClockMock) injector.getInstance(Clock.class);
+
+ busHandler = new TestBusHandler();
}
@AfterClass(groups="slow")
@@ -152,6 +173,72 @@ public class TestJaxrsBase {
}
}
+
+ protected AccountJson createAccount(String name, String key, String email) throws Exception {
+ AccountJson input = getAccountJson(name, key, email);
+ String baseJson = mapper.writeValueAsString(input);
+ Response response = doPost(BaseJaxrsResource.ACCOUNTS_PATH, baseJson, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
+ Assert.assertEquals(response.getStatusCode(), Status.CREATED.getStatusCode());
+
+ String location = response.getHeader("Location");
+ Assert.assertNotNull(location);
+
+ // Retrieves by Id based on Location returned
+ response = doGetWithUrl(location, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
+ Assert.assertEquals(response.getStatusCode(), Status.OK.getStatusCode());
+
+ baseJson = response.getResponseBody();
+ AccountJson objFromJson = mapper.readValue(baseJson, AccountJson.class);
+ Assert.assertNotNull(objFromJson);
+ return objFromJson;
+ }
+
+
+
+ protected BundleJson createBundle(String accountId, String key) throws Exception {
+ BundleJson input = new BundleJson(null, accountId, key, null);
+ String baseJson = mapper.writeValueAsString(input);
+ Response response = doPost(BaseJaxrsResource.BUNDLES_PATH, baseJson, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
+ Assert.assertEquals(response.getStatusCode(), Status.CREATED.getStatusCode());
+
+ String location = response.getHeader("Location");
+ Assert.assertNotNull(location);
+
+ // Retrieves by Id based on Location returned
+ response = doGetWithUrl(location, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
+ Assert.assertEquals(response.getStatusCode(), Status.OK.getStatusCode());
+
+ baseJson = response.getResponseBody();
+ BundleJson objFromJson = mapper.readValue(baseJson, BundleJson.class);
+ Assert.assertTrue(objFromJson.equalsNoId(input));
+ return objFromJson;
+ }
+
+ protected SubscriptionJson createSubscription(final String bundleId, final String productName, final String productCategory, final String billingPeriod) throws Exception {
+
+ SubscriptionJson input = new SubscriptionJson(null, bundleId, productName, productCategory, billingPeriod, PriceListSet.DEFAULT_PRICELIST_NAME, null, null, null);
+ String baseJson = mapper.writeValueAsString(input);
+ Response response = doPost(BaseJaxrsResource.SUBSCRIPTIONS_PATH, baseJson, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
+ Assert.assertEquals(response.getStatusCode(), Status.CREATED.getStatusCode());
+
+ String location = response.getHeader("Location");
+ Assert.assertNotNull(location);
+
+ // Retrieves by Id based on Location returned
+ response = doGetWithUrl(location, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
+ Assert.assertEquals(response.getStatusCode(), Status.OK.getStatusCode());
+
+ baseJson = response.getResponseBody();
+ SubscriptionJson objFromJson = mapper.readValue(baseJson, SubscriptionJson.class);
+ Assert.assertTrue(objFromJson.equalsNoId(input));
+ return objFromJson;
+ }
+
+
+
+ //
+ // HTTP CLIENT HELPERS
+ //
protected Response doPost(final String uri, final String body, final Map<String, String> queryParams, final int timeoutSec) {
BoundRequestBuilder builder = getBuilderWithHeaderAndQuery("POST", getUrlFromUri(uri), queryParams);
if (body != null) {
diff --git a/server/src/test/java/com/ning/billing/jaxrs/TestSubscription.java b/server/src/test/java/com/ning/billing/jaxrs/TestSubscription.java
new file mode 100644
index 0000000..8b2a055
--- /dev/null
+++ b/server/src/test/java/com/ning/billing/jaxrs/TestSubscription.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.jaxrs;
+
+import static org.testng.Assert.assertTrue;
+
+import javax.ws.rs.core.Response.Status;
+
+import org.joda.time.DateTime;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.ning.billing.beatrix.integration.TestBusHandler.NextEvent;
+import com.ning.billing.catalog.api.BillingPeriod;
+import com.ning.billing.catalog.api.Duration;
+import com.ning.billing.catalog.api.ProductCategory;
+import com.ning.billing.catalog.api.TimeUnit;
+import com.ning.billing.jaxrs.json.AccountJson;
+import com.ning.billing.jaxrs.json.BundleJson;
+import com.ning.billing.jaxrs.json.SubscriptionJson;
+import com.ning.billing.jaxrs.resources.BaseJaxrsResource;
+import com.ning.http.client.Response;
+
+public class TestSubscription extends TestJaxrsBase {
+
+ private static final Logger log = LoggerFactory.getLogger(TestSubscription.class);
+
+ private static final long DELAY = 5000;
+
+ @Test(groups="slow", enabled=true)
+ public void testSubscriptionOk() throws Exception {
+
+ AccountJson accountJson = createAccount("xil", "shdxilhkkl", "xil@yahoo.com");
+ BundleJson bundleJson = createBundle(accountJson.getAcountId(), "99999");
+
+ String productName = "Shotgun";
+ BillingPeriod term = BillingPeriod.MONTHLY;
+
+ //busHandler.pushExpectedEvent(NextEvent.CREATE);
+ //busHandler.pushExpectedEvent(NextEvent.INVOICE);
+ SubscriptionJson subscriptionJson = createSubscription(bundleJson.getBundleId(), productName, ProductCategory.BASE.toString(), term.toString());
+ //assertTrue(busHandler.isCompleted(DELAY));
+
+ // Change plan IMM
+ String newProductName = "Assault-Rifle";
+
+ SubscriptionJson newInput = new SubscriptionJson(subscriptionJson.getSubscriptionId(),
+ subscriptionJson.getBundleId(),
+ newProductName,
+ subscriptionJson.getProductCategory(),
+ subscriptionJson.getBillingPeriod(),
+ subscriptionJson.getPriceList(), null, null, null);
+ String baseJson = mapper.writeValueAsString(newInput);
+
+ String uri = BaseJaxrsResource.SUBSCRIPTIONS_PATH + "/" + subscriptionJson.getSubscriptionId().toString();
+ Response response = doPut(uri, baseJson, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
+ Assert.assertEquals(response.getStatusCode(), Status.OK.getStatusCode());
+ baseJson = response.getResponseBody();
+ SubscriptionJson objFromJson = mapper.readValue(baseJson, SubscriptionJson.class);
+ Assert.assertTrue(objFromJson.equals(newInput));
+
+ // MOVE after TRIAL
+ //busHandler.pushExpectedEvent(NextEvent.PHASE);
+ //busHandler.pushExpectedEvent(NextEvent.INVOICE);
+ //busHandler.pushExpectedEvent(NextEvent.PAYMENT);
+ clock.setDeltaFromReality(new Duration() {
+ @Override
+ public TimeUnit getUnit() {
+ return TimeUnit.MONTHS;
+ }
+ @Override
+ public int getNumber() {
+ return 1;
+ }
+ @Override
+ public DateTime addToDateTime(DateTime dateTime) {
+ return null;
+ }
+ }, 1000);
+ //assertTrue(busHandler.isCompleted(DELAY));
+
+
+ Thread.sleep(5000);
+
+ // Cancel EOT
+ uri = BaseJaxrsResource.SUBSCRIPTIONS_PATH + "/" + subscriptionJson.getSubscriptionId().toString();
+ response = doDelete(uri, DEFAULT_EMPTY_QUERY, 10000 /* DEFAULT_HTTP_TIMEOUT_SEC */);
+ Assert.assertEquals(response.getStatusCode(), Status.OK.getStatusCode());
+
+
+ // Uncancel
+ uri = BaseJaxrsResource.SUBSCRIPTIONS_PATH + "/" + subscriptionJson.getSubscriptionId().toString() + "/uncancel";
+ response = doPut(uri, baseJson, DEFAULT_EMPTY_QUERY, 10000 /* DEFAULT_HTTP_TIMEOUT_SEC */);
+ Assert.assertEquals(response.getStatusCode(), Status.OK.getStatusCode());
+ }
+
+}
diff --git a/util/src/test/java/com/ning/billing/util/bus/TestEventBus.java b/util/src/test/java/com/ning/billing/util/bus/TestEventBus.java
index 2310f1c..2078d0e 100644
--- a/util/src/test/java/com/ning/billing/util/bus/TestEventBus.java
+++ b/util/src/test/java/com/ning/billing/util/bus/TestEventBus.java
@@ -50,6 +50,11 @@ public class TestEventBus {
this.name = name;
this.value = value;
}
+
+ @Override
+ public BusEventType getBusEventType() {
+ return null;
+ }
}
public static final class MyOtherEvent implements BusEvent {
@@ -60,6 +65,11 @@ public class TestEventBus {
this.name = name;
this.value = value;
}
+
+ @Override
+ public BusEventType getBusEventType() {
+ return null;
+ }
}
public static class MyEventHandler {