killbill-aplcache
Changes
invoice/src/main/java/com/ning/billing/invoice/notification/DefaultNextBillingDateNotifier.java 1(+1 -0)
server/pom.xml 16(+16 -0)
Details
diff --git a/account/src/main/java/com/ning/billing/account/api/user/DefaultAccountUserApi.java b/account/src/main/java/com/ning/billing/account/api/user/DefaultAccountUserApi.java
index 7717aae..3daf37d 100644
--- a/account/src/main/java/com/ning/billing/account/api/user/DefaultAccountUserApi.java
+++ b/account/src/main/java/com/ning/billing/account/api/user/DefaultAccountUserApi.java
@@ -98,7 +98,7 @@ public class DefaultAccountUserApi implements com.ning.billing.account.api.Accou
try {
dao.update(account, context);
} catch (EntityPersistenceException e) {
- throw new AccountApiException(e, ErrorCode.ACCOUNT_UPDATE_FAILED);
+ throw new AccountApiException(e, e.getCode(), e.getMessage());
}
}
@@ -106,10 +106,9 @@ public class DefaultAccountUserApi implements com.ning.billing.account.api.Accou
@Override
public void updateAccount(final String externalKey, final AccountData accountData, final CallContext context) throws AccountApiException {
UUID accountId = getIdFromKey(externalKey);
- if(accountId == null) {
+ if (accountId == null) {
throw new AccountApiException(ErrorCode.ACCOUNT_DOES_NOT_EXIST_FOR_KEY, externalKey);
}
-
updateAccount(accountId, accountData, context);
}
diff --git a/invoice/src/main/java/com/ning/billing/invoice/notification/DefaultNextBillingDateNotifier.java b/invoice/src/main/java/com/ning/billing/invoice/notification/DefaultNextBillingDateNotifier.java
index bfc97e8..2f6ea8b 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/notification/DefaultNextBillingDateNotifier.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/notification/DefaultNextBillingDateNotifier.java
@@ -24,6 +24,7 @@ import org.slf4j.LoggerFactory;
import com.google.inject.Inject;
import com.ning.billing.config.InvoiceConfig;
+import com.ning.billing.config.NotificationConfig;
import com.ning.billing.entitlement.api.user.EntitlementUserApi;
import com.ning.billing.entitlement.api.user.Subscription;
import com.ning.billing.invoice.InvoiceListener;
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/AccountJson.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/AccountJson.java
index 8af2657..13ad140 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/AccountJson.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/AccountJson.java
@@ -44,7 +44,7 @@ public class AccountJson {
private final String country;
private final String phone;
-/*
+
public AccountJson(Account account) {
this.acountId = account.getId().toString();
this.name = account.getName();
@@ -62,8 +62,6 @@ public class AccountJson {
this.country = account.getCountry();
this.phone = account.getPhone();
}
-
-*/
public AccountData toAccountData() {
return new AccountData() {
@@ -139,6 +137,25 @@ public class AccountJson {
};
}
+ // Seems like Jackson (JacksonJsonProvider.readFrom(Class<Object>, Type, Annotation[], MediaType, MultivaluedMap<String,String>, InputStream) line: 443)
+ // needs us to define a default CTOR to instanciate the class first.
+ public AccountJson() {
+ this.acountId = null;
+ this.name = null;
+ this.length = null;
+ this.externalKey = null;
+ this.email = null;
+ this.billCycleDay = null;
+ this.currency = null;
+ this.paymentProvider = null;
+ this.timeZone = null;
+ this.address1 = null;
+ this.address2 = null;
+ this.company = null;
+ this.state = null;
+ this.country = null;
+ this.phone = null;
+ }
@JsonCreator
public AccountJson(@JsonProperty("account_id") String acountId,
@@ -233,4 +250,131 @@ public class AccountJson {
public String getPhone() {
return phone;
}
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result
+ + ((acountId == null) ? 0 : acountId.hashCode());
+ result = prime * result
+ + ((address1 == null) ? 0 : address1.hashCode());
+ result = prime * result
+ + ((address2 == null) ? 0 : address2.hashCode());
+ result = prime * result
+ + ((billCycleDay == null) ? 0 : billCycleDay.hashCode());
+ result = prime * result + ((company == null) ? 0 : company.hashCode());
+ result = prime * result + ((country == null) ? 0 : country.hashCode());
+ result = prime * result
+ + ((currency == null) ? 0 : currency.hashCode());
+ result = prime * result + ((email == null) ? 0 : email.hashCode());
+ result = prime * result
+ + ((externalKey == null) ? 0 : externalKey.hashCode());
+ result = prime * result + ((length == null) ? 0 : length.hashCode());
+ result = prime * result + ((name == null) ? 0 : name.hashCode());
+ result = prime * result
+ + ((paymentProvider == null) ? 0 : paymentProvider.hashCode());
+ result = prime * result + ((phone == null) ? 0 : phone.hashCode());
+ result = prime * result + ((state == null) ? 0 : state.hashCode());
+ result = prime * result
+ + ((timeZone == null) ? 0 : timeZone.hashCode());
+ return result;
+ }
+
+ // Used to check POST versus GET
+ public boolean equalsNoId(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ AccountJson other = (AccountJson) obj;
+ if (address1 == null) {
+ if (other.address1 != null)
+ return false;
+ } else if (!address1.equals(other.address1))
+ return false;
+ if (address2 == null) {
+ if (other.address2 != null)
+ return false;
+ } else if (!address2.equals(other.address2))
+ return false;
+ if (billCycleDay == null) {
+ if (other.billCycleDay != null)
+ return false;
+ } else if (!billCycleDay.equals(other.billCycleDay))
+ return false;
+ if (company == null) {
+ if (other.company != null)
+ return false;
+ } else if (!company.equals(other.company))
+ return false;
+ if (country == null) {
+ if (other.country != null)
+ return false;
+ } else if (!country.equals(other.country))
+ return false;
+ if (currency == null) {
+ if (other.currency != null)
+ return false;
+ } else if (!currency.equals(other.currency))
+ return false;
+ if (email == null) {
+ if (other.email != null)
+ return false;
+ } else if (!email.equals(other.email))
+ return false;
+ if (externalKey == null) {
+ if (other.externalKey != null)
+ return false;
+ } else if (!externalKey.equals(other.externalKey))
+ return false;
+ if (length == null) {
+ if (other.length != null)
+ return false;
+ } else if (!length.equals(other.length))
+ return false;
+ if (name == null) {
+ if (other.name != null)
+ return false;
+ } else if (!name.equals(other.name))
+ return false;
+ if (paymentProvider == null) {
+ if (other.paymentProvider != null)
+ return false;
+ } else if (!paymentProvider.equals(other.paymentProvider))
+ return false;
+ if (phone == null) {
+ if (other.phone != null)
+ return false;
+ } else if (!phone.equals(other.phone))
+ return false;
+ if (state == null) {
+ if (other.state != null)
+ return false;
+ } else if (!state.equals(other.state))
+ return false;
+ if (timeZone == null) {
+ if (other.timeZone != null)
+ return false;
+ } else if (!timeZone.equals(other.timeZone))
+ return false;
+ return true;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (equalsNoId(obj) == false) {
+ return false;
+ } else {
+ AccountJson other = (AccountJson) obj;
+ if (acountId == null) {
+ if (other.acountId != null)
+ return false;
+ } else if (!acountId.equals(other.acountId))
+ 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 0496213..7601229 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.List;
import java.util.UUID;
import javax.ws.rs.Consumes;
@@ -34,66 +35,88 @@ 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.inject.Inject;
import com.google.inject.Singleton;
+import com.ning.billing.ErrorCode;
import com.ning.billing.account.api.Account;
import com.ning.billing.account.api.AccountApiException;
import com.ning.billing.account.api.AccountData;
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.util.Context;
@Singleton
-@Path("/1.0/account")
-public class AccountResource {
+@Path(BaseJaxrsResource.ACCOUNTS_PATH)
+public class AccountResource implements BaseJaxrsResource {
private static final Logger log = LoggerFactory.getLogger(AccountResource.class);
private final AccountUserApi accountApi;
+ final EntitlementUserApi entitlementApi;
private final Context context;
@Inject
- public AccountResource(final AccountUserApi accountApi, final Context context) {
+ public AccountResource(final AccountUserApi accountApi, final EntitlementUserApi entitlementApi, final Context context) {
this.accountApi = accountApi;
+ this.entitlementApi = entitlementApi;
this.context = context;
}
@GET
- @Path("/{accountId:\\w+-\\w+-\\w+-\\w+-\\w+}")
+ @Path("/{accountId:" + UUID_PATTERN + "}")
@Produces(APPLICATION_JSON)
public Response getAccount(@PathParam("accountId") String accountId) {
Account account = accountApi.getAccountById(UUID.fromString(accountId));
if (account == null) {
- return Response.status(Status.NOT_FOUND).build();
+ return Response.status(Status.NO_CONTENT).build();
}
- AccountJson json = null; /* new AccountJson(account); */
+ AccountJson json = new AccountJson(account);
return Response.status(Status.OK).entity(json).build();
}
@GET
+ @Path("/{accountId:" + UUID_PATTERN + "}/" + BUNDLES)
@Produces(APPLICATION_JSON)
- public Response getAccountByKey(@QueryParam("externalKey") String externalKey) {
+ public Response getAccountBundles(@PathParam("accountId") String accountId) {
+ UUID uuid = UUID.fromString(accountId);
+ 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();
+ }
+
+
+ @GET
+ @Produces(APPLICATION_JSON)
+ public Response getAccountByKey(@QueryParam(QUERY_EXTERNAL_KEY) String externalKey) {
Account account = null;
if (externalKey != null) {
account = accountApi.getAccountByKey(externalKey);
}
if (account == null) {
- return Response.status(Status.NOT_FOUND).build();
+ return Response.status(Status.NO_CONTENT).build();
}
- AccountJson json = null; /* new AccountJson(account); */
+ AccountJson json = new AccountJson(account);
return Response.status(Status.OK).entity(json).build();
}
+
@POST
@Consumes(APPLICATION_JSON)
@Produces(APPLICATION_JSON)
public Response createAccount(AccountJson json) {
try {
+
AccountData data = json.toAccountData();
final Account account = accountApi.createAccount(data, null, null, context.getContext());
URI uri = UriBuilder.fromPath(account.getId().toString()).build();
@@ -112,21 +135,26 @@ public class AccountResource {
@PUT
@Consumes(APPLICATION_JSON)
@Produces(APPLICATION_JSON)
- @Path("/{accountId:\\w+-\\w+-\\w+-\\w+-\\w+}")
+ @Path("/{accountId:" + UUID_PATTERN + "}")
public Response updateAccount(AccountJson json, @PathParam("accountId") String accountId) {
try {
AccountData data = json.toAccountData();
- accountApi.updateAccount(accountId, data, context.getContext());
- return Response.status(Status.NO_CONTENT).build();
+ UUID uuid = UUID.fromString(accountId);
+ accountApi.updateAccount(uuid, data, context.getContext());
+ return getAccount(accountId);
} catch (AccountApiException e) {
- log.info(String.format("Failed to update account %s with %s", accountId, json), e);
- return Response.status(Status.BAD_REQUEST).build();
+ if (e.getCode() == ErrorCode.ACCOUNT_DOES_NOT_EXIST_FOR_ID.getCode()) {
+ return Response.status(Status.NO_CONTENT).build();
+ } else {
+ log.info(String.format("Failed to update account %s with %s", accountId, json), e);
+ return Response.status(Status.BAD_REQUEST).build();
+ }
}
}
// Not supported
@DELETE
- @Path("/{accountId:\\w+-\\w+-\\w+-\\w+-\\w+}")
+ @Path("/{accountId:" + UUID_PATTERN + "}")
@Produces(APPLICATION_JSON)
public Response cancelAccount(@PathParam("accountId") String accountId) {
/*
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
new file mode 100644
index 0000000..9eb01eb
--- /dev/null
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/BaseJaxrsResource.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.resources;
+
+public interface BaseJaxrsResource {
+
+ public static final String API_PREFIX = "";
+ public static final String API_VERSION = "/1.0";
+
+ /*
+ * Patterns
+ */
+ public static String UUID_PATTERN = "\\w+-\\w+-\\w+-\\w+-\\w+";
+
+ /*
+ * Query parameters
+ */
+ public static final String QUERY_EXTERNAL_KEY = "external_key";
+
+
+ public static final String ACCOUNTS = "accounts";
+ public static final String ACCOUNTS_PATH = API_PREFIX + API_VERSION + "/" + ACCOUNTS;
+
+ public static final String BUNDLES = "bundles";
+
+}
server/pom.xml 16(+16 -0)
diff --git a/server/pom.xml b/server/pom.xml
index bba0dd1..a624843 100644
--- a/server/pom.xml
+++ b/server/pom.xml
@@ -244,6 +244,22 @@
<artifactId>testng</artifactId>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>com.ning.billing</groupId>
+ <artifactId>killbill-util</artifactId>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>mysql</groupId>
+ <artifactId>mysql-connector-mxj</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>mysql</groupId>
+ <artifactId>mysql-connector-mxj-db-files</artifactId>
+ <scope>test</scope>
+ </dependency>
</dependencies>
<build>
<resources>
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 df96364..51091e5 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
@@ -15,27 +15,24 @@
*/
package com.ning.billing.server.listeners;
-import java.util.Set;
import com.ning.billing.beatrix.lifecycle.DefaultLifecycle;
import com.ning.billing.entitlement.api.user.SubscriptionTransition;
-import com.ning.billing.lifecycle.KillbillService;
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.server.util.ServerUtil;
import com.ning.billing.util.bus.Bus;
import com.ning.billing.util.bus.BusService;
import com.ning.jetty.base.modules.ServerModuleBuilder;
import com.ning.jetty.core.listeners.SetupServer;
-import com.ning.jetty.jdbi.config.DaoConfig;
import com.google.common.eventbus.Subscribe;
import com.google.inject.Injector;
+import com.google.inject.Module;
+
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import javax.management.RuntimeErrorException;
import javax.servlet.ServletContextEvent;
public class KillbillGuiceListener extends SetupServer
@@ -44,9 +41,14 @@ public class KillbillGuiceListener extends SetupServer
private DefaultLifecycle killbillLifecycle;
private BusService killbillBusService;
-
private KillbillEventHandler killbilleventHandler;
+ protected Injector theInjector;
+
+ protected Module getModule() {
+ return new KillbillServerModule();
+ }
+
@Override
public void contextInitialized(ServletContextEvent event)
{
@@ -56,30 +58,18 @@ public class KillbillGuiceListener extends SetupServer
.addConfig(KillbillServerConfig.class)
.addHealthCheck(KillbillHealthcheck.class)
.addJMXExport(KillbillHealthcheck.class)
- .addModule(new KillbillServerModule())
+ .addModule(getModule())
.addJerseyResource("com.ning.billing.jaxrs.resources");
-/*
- //
- // Dynamically add all killbill configs
- //
- try {
- Set<Class<?>> configs = ServerUtil.getKillbillConfig("com.ning.billing.config", "killbill-api", "com.ning.billing.config.KillbillConfig");
- for (Class<?> cur : configs) {
- builder.addConfig(cur);
- }
- } catch(ClassNotFoundException e) {
- throw new RuntimeException(e);
- }
- */
+
guiceModule = builder.build();
super.contextInitialized(event);
logger.info("KillbillLifecycleListener : contextInitialized");
- final Injector injector = injector(event);
- killbillLifecycle = injector.getInstance(DefaultLifecycle.class);
- killbillBusService = injector.getInstance(BusService.class);
+ theInjector = injector(event);
+ killbillLifecycle = theInjector.getInstance(DefaultLifecycle.class);
+ killbillBusService = theInjector.getInstance(BusService.class);
killbilleventHandler = new KillbillEventHandler();
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 5f03b42..902f69e 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
@@ -44,21 +44,18 @@ import org.skife.jdbi.v2.IDBI;
public class KillbillServerModule extends AbstractModule
{
@Override
- protected void configure()
- {
+ protected void configure() {
configureDao();
configureResources();
installKillbillModules();
}
- protected void configureDao()
- {
+ protected void configureDao() {
bind(IDBI.class).to(DBI.class).asEagerSingleton();
bind(DBI.class).toProvider(DBIProvider.class).asEagerSingleton();
}
- protected void configureResources()
- {
+ protected void configureResources() {
bind(AccountResource.class).asEagerSingleton();
bind(BundleResource.class).asEagerSingleton();
bind(SubscriptionResource.class).asEagerSingleton();
@@ -67,8 +64,7 @@ public class KillbillServerModule extends AbstractModule
bind(PaymentResource.class).asEagerSingleton();
}
- protected void installKillbillModules()
- {
+ protected void installKillbillModules() {
install(new FieldStoreModule());
install(new TagStoreModule());
install(new CatalogModule());
diff --git a/server/src/main/resources/killbill-server.properties b/server/src/main/resources/killbill-server.properties
index facf47d..daaa110 100644
--- a/server/src/main/resources/killbill-server.properties
+++ b/server/src/main/resources/killbill-server.properties
@@ -1,6 +1,7 @@
-com.ning.core.dao.url=jdbc:mysql://127.0.0.1:3306/killbill
-com.ning.core.dao.user=root
-com.ning.core.dao.password=root
+# Use skeleton properties for server and configure killbill database
+com.ning.jetty.jdbi.url=jdbc:mysql://127.0.0.1:3306/killbill
+com.ning.jetty.jdbi.user=root
+com.ning.jetty.jdbi.password=root
killbill.catalog.uri=file:src/main/resources/catalog-demo.xml
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 6eabeda..2b597df 100644
--- a/server/src/test/java/com/ning/billing/jaxrs/TestAccount.java
+++ b/server/src/test/java/com/ning/billing/jaxrs/TestAccount.java
@@ -15,205 +15,94 @@
*/
package com.ning.billing.jaxrs;
-import static org.testng.Assert.assertNotNull;
-
-import java.io.IOException;
-import java.io.StringWriter;
-import java.io.Writer;
-import java.net.URI;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.EventListener;
import java.util.HashMap;
-import java.util.Iterator;
+import java.util.Map;
+
+
+import javax.ws.rs.core.Response.Status;
-import java.util.UUID;
-import org.codehaus.jackson.map.ObjectMapper;
-import org.codehaus.jackson.map.ObjectWriter;
-import org.eclipse.jetty.servlet.FilterHolder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.testng.annotations.BeforeClass;
+import org.testng.Assert;
import org.testng.annotations.Test;
-
-
import com.ning.billing.jaxrs.json.AccountJson;
-import com.ning.billing.jaxrs.json.SubscriptionJson;
-import com.ning.billing.server.listeners.KillbillGuiceListener;
-import com.ning.http.client.AsyncCompletionHandler;
-import com.ning.http.client.AsyncHttpClient;
+import com.ning.billing.jaxrs.resources.BaseJaxrsResource;
import com.ning.http.client.Response;
-import com.ning.jetty.core.CoreConfig;
-import com.ning.jetty.core.server.HttpServer;
-public class TestAccount {
- private static final Logger log = LoggerFactory.getLogger(TestAccount.class);
+public class TestAccount extends TestJaxrsBase {
- public static final String HEADER_CONTENT_TYPE = "Content-type";
- public static final String CONTENT_TYPE = "application/json";
-
- private ObjectMapper mapper;
-
- private HttpServer server;
- private AsyncHttpClient httpClient;
- private CoreConfig config;
-
- CoreConfig getConfig() {
- return new CoreConfig() {
-
- @Override
- public boolean isSSLEnabled() {
- return false;
- }
- @Override
- public boolean isJettyStatsOn() {
- return false;
- }
- @Override
- public int getServerSslPort() {
- return 0;
- }
- @Override
- public int getServerPort() {
- return 8080;
- }
- @Override
- public String getServerHost() {
- return "127.0.0.1";
- }
- @Override
- public String getSSLkeystorePassword() {
- return null;
- }
- @Override
- public String getSSLkeystoreLocation() {
- return null;
- }
- @Override
- public int getMinThreads() {
- return 2;
- }
- @Override
- public int getMaxThreads() {
- return 100;
- }
- @Override
- public String getLogPath() {
- return "/var/tmp/.logs";
- }
- };
- }
-
- public static void loadSystemPropertiesFromClasspath(final String resource) {
- final URL url = TestAccount.class.getResource(resource);
- assertNotNull(url);
-
- try {
- System.getProperties().load( url.openStream() );
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- }
-
-
- @BeforeClass(groups="slow")
- public void setup() throws Exception {
-
- loadSystemPropertiesFromClasspath("/killbill.properties");
-
- httpClient = new AsyncHttpClient();
- server = new HttpServer();
- config = getConfig();
- mapper = new ObjectMapper();
- final Iterable<EventListener> eventListeners = new Iterable<EventListener>() {
- @Override
- public Iterator<EventListener> iterator() {
- ArrayList<EventListener> array = new ArrayList<EventListener>();
- array.add(new KillbillGuiceListener());
- return array.iterator();
- }
- };
- server.configure(config, eventListeners, new HashMap<FilterHolder, String>());
- server.start();
- }
+ private static final Logger log = LoggerFactory.getLogger(TestAccount.class);
- AccountJson getAccountJson() {
- String accountId = UUID.randomUUID().toString();
- String name = "yoyo bozo2";
- int length = 4;
- String externalKey = "xdfsdretuq";
- String email = "yoyo@gmail.com";
- int billCycleDay = 12;
- String currency = "USD";
- String paymentProvider = "paypal";
- String timeZone = "UTC";
- String address1 = "12 rue des ecoles";
- String address2 = "Poitier";
- String company = "Renault";
- String state = "Poitou";
- String country = "France";
- String phone = "81 53 26 56";
-
- AccountJson accountJson = new AccountJson(accountId, name, length, externalKey, email, billCycleDay, currency, paymentProvider, timeZone, address1, address2, company, state, country, phone);
- return accountJson;
- }
-
- @Test(groups="slow", enabled=false)
- public void testFoo() throws Exception {
+ @Test(groups="slow", enabled=true)
+ public void testAccountOk() throws Exception {
- ObjectMapper mapper = new ObjectMapper();
+ 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));
+
+ // 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);
+ Assert.assertEquals(response.getStatusCode(), Status.OK.getStatusCode());
+ baseJson = response.getResponseBody();
+ objFromJson = mapper.readValue(baseJson, AccountJson.class);
+ Assert.assertTrue(objFromJson.equalsNoId(input));
- AccountJson accountData = getAccountJson();
-
- ObjectWriter objWriter = mapper.writer();
-
- Writer writer = new StringWriter();
- objWriter.writeValue(writer, accountData);
- String baseJson = writer.toString();
-
- log.info(baseJson);
+ // Update Account
+ AccountJson newInput = new AccountJson(objFromJson.getAcountId(),
+ "zozo", 4, objFromJson.getExternalKey(), "rr@google.com", 18, "EUR", "none", "UTC", "bl1", "bh2", "", "ca", "usa", "415-255-2991");
+ baseJson = mapper.writeValueAsString(newInput);
+ final String uri = BaseJaxrsResource.ACCOUNTS_PATH + "/" + objFromJson.getAcountId();
+ response = doPut(uri, baseJson, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
+ Assert.assertEquals(response.getStatusCode(), Status.OK.getStatusCode());
+ baseJson = response.getResponseBody();
+ objFromJson = mapper.readValue(baseJson, AccountJson.class);
+ Assert.assertTrue(objFromJson.equals(newInput));
+ }
- AccountJson objFromJson = mapper.readValue(baseJson, AccountJson.class);
- log.info(objFromJson.toString());
+ @Test(groups="slow", enabled=true)
+ public void testUpdateNonExistentAccount() throws Exception {
+ AccountJson input = getAccountJson("xoxo", "shdgfhwe", "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);
+ Assert.assertEquals(response.getStatusCode(), Status.NO_CONTENT.getStatusCode());
+ String body = response.getResponseBody();
+ Assert.assertEquals(body, "");
}
- @Test(groups="slow", enabled=false)
- public void testAccountOk() throws Exception {
-
- final String accountPathPrefix = "/1.0/account";
-
- AccountJson accountData = getAccountJson();
- ObjectWriter objWriter = mapper.writer();
-
- Writer writer = new StringWriter();
- objWriter.writeValue(writer, accountData);
- String baseJson = writer.toString();
-
- try {
- Thread.sleep(100000);
- } catch (Exception e) {}
-
- httpClient.preparePost(String.format("http://%s:%d%s", config.getServerHost(), config.getServerPort(), accountPathPrefix))
- .addHeader(HEADER_CONTENT_TYPE, CONTENT_TYPE)
- .setBody(baseJson)
- .execute(new AsyncCompletionHandler<Integer>() {
-
- @Override
- public Integer onCompleted(Response response)
- throws Exception {
-
- int statusCode = response.getStatusCode();
- URI uri = response.getUri();
- return statusCode;
- }
- });
+ @Test(groups="slow", enabled=true)
+ public void testAccountNonExistent() throws Exception {
+ final String uri = BaseJaxrsResource.ACCOUNTS_PATH + "/99999999-b103-42f3-8b6e-dd244f1d0747";
+ Response response = doGet(uri, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
+ Assert.assertEquals(response.getStatusCode(), Status.NO_CONTENT.getStatusCode());
+ }
+
+ @Test(groups="slow", enabled=true)
+ public void testAccountBadAccountId() throws Exception {
+ final String uri = BaseJaxrsResource.ACCOUNTS_PATH + "/yo";
+ Response response = doGet(uri, DEFAULT_EMPTY_QUERY, DEFAULT_HTTP_TIMEOUT_SEC);
+ Assert.assertEquals(response.getStatusCode(), Status.NOT_FOUND.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
new file mode 100644
index 0000000..4db4a3b
--- /dev/null
+++ b/server/src/test/java/com/ning/billing/jaxrs/TestJaxrsBase.java
@@ -0,0 +1,291 @@
+/*
+ * 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.assertNotNull;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.EventListener;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.UUID;
+import java.util.concurrent.TimeUnit;
+
+import org.codehaus.jackson.map.ObjectMapper;
+import org.eclipse.jetty.servlet.FilterHolder;
+import org.skife.config.ConfigurationObjectFactory;
+import org.skife.jdbi.v2.IDBI;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.Assert;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+
+import com.google.inject.Injector;
+import com.google.inject.Module;
+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.server.listeners.KillbillGuiceListener;
+import com.ning.billing.server.modules.KillbillServerModule;
+import com.ning.http.client.AsyncCompletionHandler;
+import com.ning.http.client.AsyncHttpClient;
+import com.ning.http.client.AsyncHttpClient.BoundRequestBuilder;
+import com.ning.http.client.ListenableFuture;
+import com.ning.http.client.Response;
+import com.ning.jetty.core.CoreConfig;
+import com.ning.jetty.core.server.HttpServer;
+
+public class TestJaxrsBase {
+
+ protected static final int DEFAULT_HTTP_TIMEOUT_SEC = 5;
+
+ protected static final Map<String, String> DEFAULT_EMPTY_QUERY = new HashMap<String, String>();
+
+ private static final Logger log = LoggerFactory.getLogger(TestJaxrsBase.class);
+
+ public static final String HEADER_CONTENT_TYPE = "Content-type";
+ public static final String CONTENT_TYPE = "application/json";
+
+ private MysqlTestingHelper helper;
+ private HttpServer server;
+
+ protected CoreConfig config;
+ protected AsyncHttpClient httpClient;
+ protected ObjectMapper mapper;
+
+
+ public static void loadSystemPropertiesFromClasspath(final String resource) {
+ final URL url = TestJaxrsBase.class.getResource(resource);
+ assertNotNull(url);
+ try {
+ System.getProperties().load( url.openStream() );
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public static class TestKillbillGuiceListener extends KillbillGuiceListener {
+ public TestKillbillGuiceListener() {
+ super();
+ }
+ @Override
+ protected Module getModule() {
+ return new TestKillbillServerModule();
+ }
+ public Injector getTheInjector() {
+ return theInjector;
+ }
+ }
+
+ public static class TestKillbillServerModule extends KillbillServerModule {
+
+ @Override
+ protected void configureDao() {
+ final MysqlTestingHelper helper = new MysqlTestingHelper();
+ bind(MysqlTestingHelper.class).toInstance(helper);
+ if (helper.isUsingLocalInstance()) {
+ bind(IDBI.class).toProvider(DBIProvider.class).asEagerSingleton();
+ final DbiConfig config = new ConfigurationObjectFactory(System.getProperties()).build(DbiConfig.class);
+ bind(DbiConfig.class).toInstance(config);
+ } else {
+ final IDBI dbi = helper.getDBI();
+ bind(IDBI.class).toInstance(dbi);
+ }
+ }
+ }
+
+
+
+ @BeforeClass(groups="slow")
+ public void setup() throws Exception {
+
+ loadSystemPropertiesFromClasspath("/killbill.properties");
+
+ final EventListener eventListener = new TestKillbillGuiceListener();
+ httpClient = new AsyncHttpClient();
+ server = new HttpServer();
+ config = getConfig();
+ mapper = new ObjectMapper();
+ final Iterable<EventListener> eventListeners = new Iterable<EventListener>() {
+ @Override
+ public Iterator<EventListener> iterator() {
+ ArrayList<EventListener> array = new ArrayList<EventListener>();
+ array.add(eventListener);
+ return array.iterator();
+ }
+ };
+ server.configure(config, eventListeners, new HashMap<FilterHolder, String>());
+ server.start();
+
+ Injector injector = ((TestKillbillGuiceListener) eventListener).getTheInjector();
+
+ helper = injector.getInstance(MysqlTestingHelper.class);
+ helper.cleanupAllTables();
+ }
+
+ @AfterClass(groups="slow")
+ public void tearDown() {
+ if (helper != null) {
+ try {
+ helper.startMysql();
+ } catch (IOException ignore) {
+ }
+ }
+ }
+
+ 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) {
+ builder.setBody(body);
+ }
+ return executeAndWait(builder, timeoutSec);
+ }
+
+ protected Response doPut(final String uri, final String body, final Map<String, String> queryParams, final int timeoutSec) {
+ final String url = String.format("http://%s:%d%s", config.getServerHost(), config.getServerPort(), uri);
+ BoundRequestBuilder builder = getBuilderWithHeaderAndQuery("PUT", url, queryParams);
+ if (body != null) {
+ builder.setBody(body);
+ }
+ return executeAndWait(builder, timeoutSec);
+ }
+
+ protected Response doDelete(final String uri, final Map<String, String> queryParams, final int timeoutSec) {
+ final String url = String.format("http://%s:%d%s", config.getServerHost(), config.getServerPort(), uri);
+ BoundRequestBuilder builder = getBuilderWithHeaderAndQuery("DELETE", url, queryParams);
+ return executeAndWait(builder, timeoutSec);
+ }
+
+ protected Response doGet(final String uri, final Map<String, String> queryParams, final int timeoutSec) {
+ final String url = String.format("http://%s:%d%s", config.getServerHost(), config.getServerPort(), uri);
+ return doGetWithUrl(url, queryParams, timeoutSec);
+ }
+
+ protected Response doGetWithUrl(final String url, final Map<String, String> queryParams, final int timeoutSec) {
+ BoundRequestBuilder builder = getBuilderWithHeaderAndQuery("GET", url, queryParams);
+ return executeAndWait(builder, timeoutSec);
+ }
+
+ private Response executeAndWait(final BoundRequestBuilder builder, final int timeoutSec) {
+ Response response = null;
+ try {
+ ListenableFuture<Response> futureStatus =
+ builder.execute(new AsyncCompletionHandler<Response>() {
+ @Override
+ public Response onCompleted(Response response) throws Exception {
+ return response;
+ }
+ });
+ response = futureStatus.get(timeoutSec, TimeUnit.SECONDS);
+ } catch (Exception e) {
+ Assert.fail(e.getMessage());
+ }
+ Assert.assertNotNull(response);
+ return response;
+ }
+
+ private String getUrlFromUri(final String uri) {
+ return String.format("http://%s:%d%s", config.getServerHost(), config.getServerPort(), uri);
+ }
+
+ private BoundRequestBuilder getBuilderWithHeaderAndQuery(final String verb, final String url, final Map<String, String> queryParams) {
+ BoundRequestBuilder builder = null;
+ if (verb.equals("GET")) {
+ builder = httpClient.prepareGet(url);
+ } else if (verb.equals("POST")) {
+ builder = httpClient.preparePost(url);
+ } else if (verb.equals("PUT")) {
+ builder = httpClient.preparePut(url);
+ } else if (verb.equals("DELETE")) {
+ builder = httpClient.prepareDelete(url);
+ }
+ builder.addHeader(HEADER_CONTENT_TYPE, CONTENT_TYPE);
+ for (Entry<String, String> q : queryParams.entrySet()) {
+ builder.addQueryParameter(q.getKey(), q.getValue());
+ }
+ return builder;
+ }
+
+ public AccountJson getAccountJson(final String name, final String externalKey, final String email) {
+ String accountId = UUID.randomUUID().toString();
+ int length = 4;
+ int billCycleDay = 12;
+ String currency = "USD";
+ String paymentProvider = "paypal";
+ String timeZone = "UTC";
+ String address1 = "12 rue des ecoles";
+ String address2 = "Poitier";
+ String company = "Renault";
+ String state = "Poitou";
+ String country = "France";
+ String phone = "81 53 26 56";
+
+ AccountJson accountJson = new AccountJson(accountId, name, length, externalKey, email, billCycleDay, currency, paymentProvider, timeZone, address1, address2, company, state, country, phone);
+ return accountJson;
+ }
+
+
+ private CoreConfig getConfig() {
+ return new CoreConfig() {
+ @Override
+ public boolean isSSLEnabled() {
+ return false;
+ }
+ @Override
+ public boolean isJettyStatsOn() {
+ return false;
+ }
+ @Override
+ public int getServerSslPort() {
+ return 0;
+ }
+ @Override
+ public int getServerPort() {
+ return 8080;
+ }
+ @Override
+ public String getServerHost() {
+ return "127.0.0.1";
+ }
+ @Override
+ public String getSSLkeystorePassword() {
+ return null;
+ }
+ @Override
+ public String getSSLkeystoreLocation() {
+ return null;
+ }
+ @Override
+ public int getMinThreads() {
+ return 2;
+ }
+ @Override
+ public int getMaxThreads() {
+ return 100;
+ }
+ @Override
+ public String getLogPath() {
+ return "/var/tmp/.logs";
+ }
+ };
+ }
+}
diff --git a/server/src/test/resources/killbill.properties b/server/src/test/resources/killbill.properties
index 251d154..c3fe203 100644
--- a/server/src/test/resources/killbill.properties
+++ b/server/src/test/resources/killbill.properties
@@ -1,4 +1,5 @@
-com.ning.jetty.jdbi.url=jdbc:mysql://127.0.0.1:3306/killbill
+# Use killbill util test properties (DbiProvider/MysqltestingHelper) on the test side configured with test_killbill
+com.ning.billing.dbi.jdbc.url=jdbc:mysql://127.0.0.1:3306/test_killbill
killbill.catalog.uri=file:src/test/resources/catalog-weapons.xml
@@ -8,4 +9,7 @@ killbill.payment.retry.days=8,8,8
user.timezone=UTC
+com.ning.billing.dbi.test.useLocalDb=true
+
+
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 866289e..9995229 100644
--- a/util/src/test/java/com/ning/billing/dbi/MysqlTestingHelper.java
+++ b/util/src/test/java/com/ning/billing/dbi/MysqlTestingHelper.java
@@ -20,6 +20,7 @@ import java.io.File;
import java.io.IOException;
import java.net.ServerSocket;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import org.apache.commons.io.FileUtils;
@@ -27,6 +28,7 @@ import org.skife.jdbi.v2.DBI;
import org.skife.jdbi.v2.Handle;
import org.skife.jdbi.v2.IDBI;
import org.skife.jdbi.v2.tweak.HandleCallback;
+import org.skife.jdbi.v2.util.StringMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testng.Assert;
@@ -48,6 +50,8 @@ public class MysqlTestingHelper
private static final String USERNAME = "root";
private static final String PASSWORD = "root";
+ // Discover dynamically list of all tables in that database;
+ private List<String> allTables;
private File dbDir;
private MysqldResource mysqldResource;
private int port;
@@ -122,7 +126,36 @@ public class MysqlTestingHelper
}
});
}
+
+ public void cleanupAllTables() {
+ final List<String> tablesToCleanup = fetchAllTables();
+ for (String tableName : tablesToCleanup) {
+ cleanupTable(tableName);
+ }
+ }
+
+ public synchronized List<String> fetchAllTables() {
+
+ if (allTables == null) {
+ final String dbiString = "jdbc:mysql://localhost:" + port + "/information_schema";
+ IDBI cleanupDbi = new DBI(dbiString, USERNAME, PASSWORD);
+
+ final List<String> tables= cleanupDbi.withHandle(new HandleCallback<List<String>>() {
+
+ @Override
+ public List<String> withHandle(Handle h) throws Exception {
+ return h.createQuery("select table_name from tables where table_schema = :table_schema and table_type = 'BASE TABLE';")
+ .bind("table_schema", DB_NAME)
+ .map(new StringMapper())
+ .list();
+ }
+ });
+ allTables = tables;
+ }
+ return allTables;
+ }
+
public void stopMysql()
{
if (mysqldResource != null) {