killbill-memoizeit
Changes
account/pom.xml 2(+1 -1)
analytics/pom.xml 2(+1 -1)
api/pom.xml 2(+1 -1)
beatrix/pom.xml 14(+13 -1)
beatrix/src/test/resources/log4j.xml 36(+36 -0)
catalog/pom.xml 2(+1 -1)
entitlement/pom.xml 2(+1 -1)
entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCancelMemory.java 3(+1 -2)
entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiChangePlanMemory.java 2(+1 -1)
entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCreateMemory.java 2(+1 -1)
invoice/pom.xml 2(+1 -1)
payment/pom.xml 2(+1 -1)
pom.xml 7(+6 -1)
util/pom.xml 2(+1 -1)
Details
account/pom.xml 2(+1 -1)
diff --git a/account/pom.xml b/account/pom.xml
index e88235d..acec6a7 100644
--- a/account/pom.xml
+++ b/account/pom.xml
@@ -13,7 +13,7 @@
<parent>
<groupId>com.ning.billing</groupId>
<artifactId>killbill</artifactId>
- <version>0.0.8-SNAPSHOT</version>
+ <version>0.0.9-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-account</artifactId>
diff --git a/account/src/main/java/com/ning/billing/account/api/AccountService.java b/account/src/main/java/com/ning/billing/account/api/AccountService.java
new file mode 100644
index 0000000..0ce4941
--- /dev/null
+++ b/account/src/main/java/com/ning/billing/account/api/AccountService.java
@@ -0,0 +1,47 @@
+/*
+ * 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.account.api;
+
+import com.google.inject.Inject;
+import com.ning.billing.lifecycle.LyfecycleHandlerType;
+import com.ning.billing.lifecycle.LyfecycleHandlerType.LyfecycleLevel;
+
+public class AccountService implements IAccountService {
+
+ private static final String ACCOUNT_SERVICE_NAME = "account-service";
+
+ private final IAccountUserApi accountApi;
+
+ @Inject
+ public AccountService(IAccountUserApi api) {
+ this.accountApi = api;
+ }
+
+ @Override
+ public String getName() {
+ return ACCOUNT_SERVICE_NAME;
+ }
+
+ @Override
+ public IAccountUserApi getAccountUserApi() {
+ return accountApi;
+ }
+
+ @LyfecycleHandlerType(LyfecycleLevel.INIT_SERVICE)
+ public void initialize() {
+ }
+}
diff --git a/account/src/main/java/com/ning/billing/account/glue/AccountModule.java b/account/src/main/java/com/ning/billing/account/glue/AccountModule.java
index 4f0ec7a..ce44014 100644
--- a/account/src/main/java/com/ning/billing/account/glue/AccountModule.java
+++ b/account/src/main/java/com/ning/billing/account/glue/AccountModule.java
@@ -19,7 +19,9 @@ package com.ning.billing.account.glue;
import org.skife.config.ConfigurationObjectFactory;
import com.google.inject.AbstractModule;
+import com.ning.billing.account.api.AccountService;
import com.ning.billing.account.api.AccountUserApi;
+import com.ning.billing.account.api.IAccountService;
import com.ning.billing.account.api.IAccountUserApi;
import com.ning.billing.account.dao.AccountDao;
import com.ning.billing.account.dao.IAccountDao;
@@ -39,11 +41,16 @@ public class AccountModule extends AbstractModule {
bind(IAccountUserApi.class).to(AccountUserApi.class).asEagerSingleton();
}
+ protected void installAcountService() {
+ bind(IAccountService.class).to(AccountService.class).asEagerSingleton();
+ }
+
@Override
protected void configure() {
installConfig();
installAccountDao();
installAccountUserApi();
+ installAcountService();
}
}
analytics/pom.xml 2(+1 -1)
diff --git a/analytics/pom.xml b/analytics/pom.xml
index af0ec44..ee73d47 100644
--- a/analytics/pom.xml
+++ b/analytics/pom.xml
@@ -13,7 +13,7 @@
<parent>
<groupId>com.ning.billing</groupId>
<artifactId>killbill</artifactId>
- <version>0.0.8-SNAPSHOT</version>
+ <version>0.0.9-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-analytics</artifactId>
diff --git a/analytics/src/main/java/com/ning/billing/analytics/AnalyticsListener.java b/analytics/src/main/java/com/ning/billing/analytics/AnalyticsListener.java
index f58f601..653a285 100644
--- a/analytics/src/main/java/com/ning/billing/analytics/AnalyticsListener.java
+++ b/analytics/src/main/java/com/ning/billing/analytics/AnalyticsListener.java
@@ -38,7 +38,6 @@ public class AnalyticsListener implements IApiListener
private final IEntitlementUserApi entitlementApi;
private final IAccountUserApi accountApi;
- @Inject
public AnalyticsListener(final EventDao dao, final IEntitlementUserApi entitlementApi, final IAccountUserApi accountApi)
{
this.dao = dao;
api/pom.xml 2(+1 -1)
diff --git a/api/pom.xml b/api/pom.xml
index 14df9c9..088a2ce 100644
--- a/api/pom.xml
+++ b/api/pom.xml
@@ -13,7 +13,7 @@
<parent>
<groupId>com.ning.billing</groupId>
<artifactId>killbill</artifactId>
- <version>0.0.8-SNAPSHOT</version>
+ <version>0.0.9-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-api</artifactId>
diff --git a/api/src/main/java/com/ning/billing/account/api/IAccountService.java b/api/src/main/java/com/ning/billing/account/api/IAccountService.java
new file mode 100644
index 0000000..fa5a9fe
--- /dev/null
+++ b/api/src/main/java/com/ning/billing/account/api/IAccountService.java
@@ -0,0 +1,24 @@
+/*
+ * 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.account.api;
+
+import com.ning.billing.lifecycle.IService;
+
+public interface IAccountService extends IService {
+
+ public IAccountUserApi getAccountUserApi();
+}
diff --git a/api/src/main/java/com/ning/billing/lifecycle/IService.java b/api/src/main/java/com/ning/billing/lifecycle/IService.java
index 2e4a27f..4e4d6d1 100644
--- a/api/src/main/java/com/ning/billing/lifecycle/IService.java
+++ b/api/src/main/java/com/ning/billing/lifecycle/IService.java
@@ -45,30 +45,5 @@ public interface IService {
*/
public String getName();
- /**
- *
- * @throws ServiceException
- *
- * Initialize the service prior to start
- */
- public void initialize()
- throws ServiceException;
-
- /**
- *
- * @throws ServiceException
- *
- * Start the given service
- */
- public void start()
- throws ServiceException;
-
- /**
- * Stop the given service
- *
- * @throws ServiceException
- */
- public void stop()
- throws ServiceException;
}
diff --git a/api/src/main/java/com/ning/billing/lifecycle/Lifecycled.java b/api/src/main/java/com/ning/billing/lifecycle/Lifecycled.java
new file mode 100644
index 0000000..df1fb82
--- /dev/null
+++ b/api/src/main/java/com/ning/billing/lifecycle/Lifecycled.java
@@ -0,0 +1,27 @@
+/*
+ * 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.lifecycle;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+public @interface Lifecycled {
+}
diff --git a/api/src/main/java/com/ning/billing/lifecycle/LyfecycleHandlerType.java b/api/src/main/java/com/ning/billing/lifecycle/LyfecycleHandlerType.java
new file mode 100644
index 0000000..520fca4
--- /dev/null
+++ b/api/src/main/java/com/ning/billing/lifecycle/LyfecycleHandlerType.java
@@ -0,0 +1,91 @@
+/*
+ * 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.lifecycle;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.METHOD)
+public @interface LyfecycleHandlerType {
+
+
+ //
+ // The level themselves are still work in progress depending on what we really need
+ //
+ public enum LyfecycleLevel {
+
+ /**
+ * Load and validate catalog (only for catalog subsytem)
+ */
+ LOAD_CATALOG(Sequence.STARTUP),
+ /**
+ * Initialize event bus (only for the event bus)
+ */
+ INIT_BUS(Sequence.STARTUP),
+ /**
+ * Service specific initalization
+ */
+ INIT_SERVICE(Sequence.STARTUP),
+ /**
+ * Service register their interest in events
+ */
+ REGISTER_EVENTS(Sequence.STARTUP),
+ /**
+ * Service start
+ * - API call should not work
+ * - Events might be triggered
+ * - Batch processing jobs started
+ */
+ START_SERVICE(Sequence.STARTUP),
+ /**
+ * Stop service
+ */
+ STOP_SERVICE(Sequence.SHUTOWN),
+ /**
+ * Unregister interest in events
+ */
+ UNREGISTER_EVENTS(Sequence.SHUTOWN),
+ /**
+ * Stop bus
+ */
+ STOP_BUS(Sequence.SHUTOWN),
+ /**
+ * Any service specific shutdown action before the end
+ */
+ SHUTDOWN(Sequence.SHUTOWN);
+
+ public enum Sequence {
+ STARTUP,
+ SHUTOWN
+ };
+
+ private Sequence seq;
+
+ LyfecycleLevel(Sequence seq) {
+ this.seq = seq;
+ }
+
+ public Sequence getSequence() {
+ return seq;
+ }
+ }
+
+ public LyfecycleLevel value();
+}
beatrix/pom.xml 14(+13 -1)
diff --git a/beatrix/pom.xml b/beatrix/pom.xml
index dee6794..d33ef7e 100644
--- a/beatrix/pom.xml
+++ b/beatrix/pom.xml
@@ -13,7 +13,7 @@
<parent>
<groupId>com.ning.billing</groupId>
<artifactId>killbill</artifactId>
- <version>0.0.8-SNAPSHOT</version>
+ <version>0.0.9-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-beatrix</artifactId>
@@ -25,6 +25,18 @@
<artifactId>killbill-api</artifactId>
</dependency>
<dependency>
+ <groupId>com.ning.billing</groupId>
+ <artifactId>killbill-entitlement</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.ning.billing</groupId>
+ <artifactId>killbill-catalog</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ </dependency>
+ <dependency>
<groupId>com.jolbox</groupId>
<artifactId>bonecp</artifactId>
</dependency>
diff --git a/beatrix/src/main/java/com/ning/billing/beatrix/glue/BeatrixModule.java b/beatrix/src/main/java/com/ning/billing/beatrix/glue/BeatrixModule.java
new file mode 100644
index 0000000..7a672c1
--- /dev/null
+++ b/beatrix/src/main/java/com/ning/billing/beatrix/glue/BeatrixModule.java
@@ -0,0 +1,29 @@
+/*
+ * 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.beatrix.glue;
+
+import com.google.inject.AbstractModule;
+import com.ning.billing.beatrix.lifecycle.Lifecycle;
+
+public class BeatrixModule extends AbstractModule {
+
+ @Override
+ protected void configure() {
+ bind(Lifecycle.class).asEagerSingleton();
+ }
+
+}
diff --git a/beatrix/src/main/java/com/ning/billing/beatrix/lifecycle/Lifecycle.java b/beatrix/src/main/java/com/ning/billing/beatrix/lifecycle/Lifecycle.java
new file mode 100644
index 0000000..6abdb75
--- /dev/null
+++ b/beatrix/src/main/java/com/ning/billing/beatrix/lifecycle/Lifecycle.java
@@ -0,0 +1,164 @@
+/*
+ * 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.beatrix.lifecycle;
+
+import java.lang.reflect.Method;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CopyOnWriteArraySet;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Supplier;
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.Multimap;
+import com.google.common.collect.Multimaps;
+import com.google.common.collect.SetMultimap;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import com.ning.billing.lifecycle.IService;
+import com.ning.billing.lifecycle.LyfecycleHandlerType;
+import com.ning.billing.lifecycle.LyfecycleHandlerType.LyfecycleLevel;
+import com.ning.billing.lifecycle.LyfecycleHandlerType.LyfecycleLevel.Sequence;
+
+
+public class Lifecycle {
+
+ private final static Logger log = LoggerFactory.getLogger(Lifecycle.class);
+ private final SetMultimap<LyfecycleLevel, LifecycleHandler<? extends IService>> handlersByLevel;
+
+ private final ServiceFinder serviceFinder;
+
+ private final Injector injector;
+
+ @Inject
+ public Lifecycle(Injector injector) {
+
+ this.serviceFinder = new ServiceFinder(Lifecycle.class.getClassLoader());
+ this.handlersByLevel = Multimaps.newSetMultimap(new ConcurrentHashMap<LyfecycleLevel, Collection<LifecycleHandler<? extends IService>>>(),
+
+ new Supplier<Set<LifecycleHandler<? extends IService>>>() {
+ @Override
+ public Set<LifecycleHandler<? extends IService>> get() {
+ return new CopyOnWriteArraySet<LifecycleHandler<? extends IService>>();
+ }
+ });
+ this.injector = injector;
+
+ init();
+ }
+
+ public void init() {
+ Set<? extends IService> services = findServices();
+ Iterator<? extends IService> it = services.iterator();
+ while (it.hasNext()) {
+ handlersByLevel.putAll(findAllHandlers(it.next()));
+ }
+ }
+
+ public void fireStartupSequence() {
+ for (LyfecycleLevel level : LyfecycleLevel.values()) {
+ if (level.getSequence() == Sequence.SHUTOWN) {
+ break;
+ }
+ doFireStage(level);
+ }
+ }
+
+ public void fireShutdownSequence() {
+ for (LyfecycleLevel level : LyfecycleLevel.values()) {
+ if (level.getSequence() == Sequence.STARTUP) {
+ continue;
+ }
+ doFireStage(level);
+ }
+ }
+
+ private void doFireStage(LyfecycleLevel level) {
+ log.info("Killbill lifecycle firing stage {}", level);
+ Set<LifecycleHandler<? extends IService>> handlers = handlersByLevel.get(level);
+ for (LifecycleHandler<? extends IService> cur : handlers) {
+
+ try {
+ Method method = cur.getMethod();
+ IService target = cur.getTarget();
+ log.info("Killbill lifecycle calling handler {} for service {}", cur.getMethod().getName(), target.getName());
+ method.invoke(target);
+ } catch (Exception e) {
+ log.warn("Killbill lifecycle failed to invoke lifecycle handler", e);
+ }
+ }
+
+ }
+
+ private Set<? extends IService> findServices() {
+
+ Set<IService> result = new HashSet<IService>();
+ Set<Class<? extends IService>> services = serviceFinder.getServices();
+ for (Class<? extends IService> cur : services) {
+ log.debug("Found service {}", cur.getName());
+ try {
+ IService instance = injector.getInstance(cur);
+ log.debug("got instance {}", instance.getName());
+ result.add(instance);
+ } catch (Exception e) {
+ log.warn("Failed to inject " + cur.getName(), e);
+ }
+
+ }
+ return result;
+ }
+
+
+ public Multimap<LyfecycleLevel, LifecycleHandler<? extends IService>> findAllHandlers(IService service) {
+ Multimap<LyfecycleLevel, LifecycleHandler<? extends IService>> methodsInService =
+ HashMultimap.create();
+ Class<? extends IService> clazz = service.getClass();
+ for (Method method : clazz.getMethods()) {
+ LyfecycleHandlerType annotation = method.getAnnotation(LyfecycleHandlerType.class);
+ if (annotation != null) {
+ LyfecycleLevel level = annotation.value();
+ LifecycleHandler<? extends IService> handler = new LifecycleHandler<IService>(service, method);
+ methodsInService.put(level, handler);
+ }
+ }
+ return methodsInService;
+ }
+
+
+ private final class LifecycleHandler<T> {
+ private final T target;
+ private final Method method;
+
+ public LifecycleHandler(T target, Method method) {
+ this.target = target;
+ this.method = method;
+ }
+
+ public T getTarget() {
+ return target;
+ }
+
+ public Method getMethod() {
+ return method;
+ }
+ }
+}
diff --git a/beatrix/src/main/java/com/ning/billing/beatrix/lifecycle/ServiceFinder.java b/beatrix/src/main/java/com/ning/billing/beatrix/lifecycle/ServiceFinder.java
new file mode 100644
index 0000000..fe3f0c5
--- /dev/null
+++ b/beatrix/src/main/java/com/ning/billing/beatrix/lifecycle/ServiceFinder.java
@@ -0,0 +1,212 @@
+/*
+ * 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.beatrix.lifecycle;
+
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.Modifier;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.jar.JarFile;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.ning.billing.lifecycle.IService;
+
+public class ServiceFinder {
+
+ private static final Logger log = LoggerFactory.getLogger(ServiceFinder.class);
+
+ private final ClassLoader loader;
+ private final Set<Class<? extends IService>> servicesTypes;
+
+ public ServiceFinder(ClassLoader loader) {
+ this.loader = loader;
+ this.servicesTypes = initialize();
+ Iterator<Class<? extends IService>> it = servicesTypes.iterator();
+ while (it.hasNext()) {
+ Class<? extends IService> svc = it.next();
+ log.debug("Found IService classes {}", svc.getName());
+ }
+ }
+
+ public Set<Class<? extends IService>> getServices() {
+ return servicesTypes;
+ }
+
+ private Set<Class<? extends IService>> initialize() {
+ try {
+
+ final Set<String> packageFilter = new HashSet<String>();
+ packageFilter.add("com.ning.billing");
+ final String jarFilter = "killbill";
+ return findClasses(loader, IService.class.getName().toString(), jarFilter, packageFilter);
+ } catch (ClassNotFoundException nfe) {
+ throw new RuntimeException("Failed to initialize ClassFinder", nfe);
+ }
+ }
+
+ /*
+ * Code originally from Kris Dover <krisdover@hotmail.com> and adapted for my purpose.
+ *
+ */
+ private static Set<Class<? extends IService>> findClasses(ClassLoader classLoader,
+ String interfaceFilter,
+ String jarFilter,
+ Set<String> packageFilter)
+ throws ClassNotFoundException {
+
+ final Set<Class<? extends IService>> result = new HashSet<Class<? extends IService>>();
+
+ Object[] classPaths;
+ try {
+ classPaths = ((java.net.URLClassLoader) classLoader).getURLs();
+ } catch(ClassCastException cce){
+ classPaths = System.getProperty("java.class.path", "").split(File.pathSeparator);
+ }
+
+ for (int h = 0; h < classPaths.length; h++) {
+
+
+ Enumeration<?> files = null;
+ JarFile module = null;
+ File classPath = new File( (URL.class).isInstance(classPaths[h]) ?
+ ((URL)classPaths[h]).getFile() : classPaths[h].toString());
+ if (classPath.isDirectory()) {
+ List<String> dirListing = new ArrayList<String>();
+ recursivelyListDir(dirListing, classPath, new StringBuffer() );
+ files = Collections.enumeration( dirListing );
+ } else if (classPath.getName().endsWith(".jar")) {
+ String [] jarParts = classPath.getName().split("/");
+ String jarName = jarParts[jarParts.length - 1];
+ if (jarFilter != null && jarName != null && ! jarName.startsWith(jarFilter)) {
+ continue;
+ }
+ boolean failed = true;
+ try {
+ module = new JarFile(classPath);
+ failed = false;
+ } catch (MalformedURLException mue){
+ throw new ClassNotFoundException("Bad classpath. Error: " + mue.getMessage());
+ } catch (IOException io){
+ throw new ClassNotFoundException("jar file '" + classPath.getName() +
+ "' could not be instantiate from file path. Error: " + io.getMessage());
+ }
+ if (! failed) {
+ files = module.entries();
+ }
+ }
+
+ while( files != null && files.hasMoreElements() ){
+ String fileName = files.nextElement().toString();
+
+ if( fileName.endsWith(".class") ){
+ String className = fileName.replaceAll("/", ".").substring(0, fileName.length() - 6);
+ if (packageFilter != null) {
+ boolean skip = true;
+ Iterator<String> it = packageFilter.iterator();
+ while (it.hasNext()) {
+ String filter = it.next() + ".";
+ if (className.startsWith(filter)) {
+ skip = false;
+ break;
+ }
+ }
+ if (skip) {
+ continue;
+ }
+ }
+ Class<?> theClass = null;
+ try {
+ theClass = Class.forName(className, false, classLoader);
+ } catch(NoClassDefFoundError e) {
+ continue;
+ }
+ if ( theClass.isInterface() ) {
+ continue;
+ }
+ Class<?> [] classInterfaces = getAllInterfaces(theClass);
+ String interfaceName = null;
+ for (int i = 0; i < classInterfaces.length; i++) {
+
+ interfaceName = classInterfaces[i].getName();
+ if (!interfaceFilter.equals(interfaceName) ) {
+ continue;
+ }
+ result.add((Class<? extends IService>) theClass);
+ break;
+ }
+
+ }
+ }
+ if (module != null) {
+ try {
+ module.close();
+ } catch(IOException ioe) {
+ throw new ClassNotFoundException("The module jar file '" + classPath.getName() +
+ "' could not be closed. Error: " + ioe.getMessage());
+ }
+ }
+ }
+ return result;
+ }
+
+ private static Class<?> [] getAllInterfaces(Class<?> theClass) {
+ Set<Class<?>> superInterfaces = new HashSet<Class<?>>();
+ Class<?> [] classInterfaces = theClass.getInterfaces();
+ for (Class<?> cur : classInterfaces) {
+ getSuperInterfaces(superInterfaces, cur);
+ }
+ return superInterfaces.toArray(new Class<?>[superInterfaces.size()]);
+ }
+
+ private static void getSuperInterfaces(Set<Class<?>> superInterfaces, Class<?> theInterface) {
+
+ superInterfaces.add(theInterface);
+ Class<?> [] classInterfaces = theInterface.getInterfaces();
+ for (Class<?> cur : classInterfaces) {
+ getSuperInterfaces(superInterfaces, cur);
+ }
+ }
+
+ private static void recursivelyListDir(List<String> dirListing, File dir, StringBuffer relativePath){
+ int prevLen;
+ if (dir.isDirectory()) {
+ File[] files = dir.listFiles();
+ for(int i = 0; i < files.length; i++){
+ prevLen = relativePath.length();
+ recursivelyListDir(dirListing, files[i],
+ relativePath.append(prevLen == 0 ? "" : "/" ).append( files[i].getName()));
+ relativePath.delete(prevLen, relativePath.length());
+ }
+ } else {
+ dirListing.add(relativePath.toString());
+ }
+ }
+}
diff --git a/beatrix/src/test/java/com/ning/billing/beatrix/lifecycle/TestLifecycle.java b/beatrix/src/test/java/com/ning/billing/beatrix/lifecycle/TestLifecycle.java
new file mode 100644
index 0000000..f85232f
--- /dev/null
+++ b/beatrix/src/test/java/com/ning/billing/beatrix/lifecycle/TestLifecycle.java
@@ -0,0 +1,103 @@
+/*
+ * 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.beatrix.lifecycle;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.Stage;
+import com.ning.billing.lifecycle.IService;
+import com.ning.billing.lifecycle.Lifecycled;
+import com.ning.billing.lifecycle.LyfecycleHandlerType;
+import com.ning.billing.lifecycle.LyfecycleHandlerType.LyfecycleLevel;
+
+
+public class TestLifecycle {
+
+ private final static Logger log = LoggerFactory.getLogger(TestLifecycle.class);
+
+ private Service1 s1;
+ private Service2 s2;
+
+ private Lifecycle lifecycle;
+
+ public static class Service1 implements IService {
+
+ @LyfecycleHandlerType(LyfecycleLevel.INIT_BUS)
+ public void initBus() {
+ log.info("Service1 : got INIT_BUS");
+ }
+
+ @LyfecycleHandlerType(LyfecycleLevel.START_SERVICE)
+ public void startService() {
+ log.info("Service1 : got START_SERVICE");
+ }
+
+ @Override
+ public String getName() {
+ return null;
+ }
+ }
+
+ @Lifecycled
+ public static class Service2 implements IService {
+
+ @LyfecycleHandlerType(LyfecycleLevel.LOAD_CATALOG)
+ public void loadCatalog() {
+ log.info("Service1 : got LOAD_CATALOG");
+ }
+
+ @Override
+ public String getName() {
+ return null;
+ }
+
+ }
+
+
+
+ @BeforeClass(groups={"fast"})
+ public void setup() {
+ final Injector g = Guice.createInjector(Stage.DEVELOPMENT, new TestLifecycleModule());
+ s1 = g.getInstance(Service1.class);
+ s2 = g.getInstance(Service2.class);
+ lifecycle = g.getInstance(Lifecycle.class);
+ }
+
+ @Test
+ public void testLifecycle() {
+ lifecycle.fireStartupSequence();
+ }
+
+
+ public static class TestLifecycleModule extends AbstractModule {
+
+ @Override
+ protected void configure() {
+ bind(Lifecycle.class).asEagerSingleton();
+ bind(Service1.class).asEagerSingleton();
+ bind(Service2.class).asEagerSingleton();
+ }
+
+ }
+}
+
beatrix/src/test/resources/log4j.xml 36(+36 -0)
diff --git a/beatrix/src/test/resources/log4j.xml b/beatrix/src/test/resources/log4j.xml
new file mode 100644
index 0000000..75abc76
--- /dev/null
+++ b/beatrix/src/test/resources/log4j.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
+<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
+ <appender name="stdout" class="org.apache.log4j.ConsoleAppender">
+ <param name="Target" value="System.out"/>
+ <layout class="org.apache.log4j.PatternLayout">
+ <param name="ConversionPattern" value="%p %d{ISO8601} %X{trace} %t %c %m%n"/>
+ </layout>
+ </appender>
+
+
+ <logger name="com.ning.billing.entitlement">
+ <level value="info"/>
+ </logger>
+
+ <root>
+ <priority value="info"/>
+ <appender-ref ref="stdout"/>
+ </root>
+</log4j:configuration>
catalog/pom.xml 2(+1 -1)
diff --git a/catalog/pom.xml b/catalog/pom.xml
index f43c6f7..943d49f 100644
--- a/catalog/pom.xml
+++ b/catalog/pom.xml
@@ -13,7 +13,7 @@
<parent>
<groupId>com.ning.billing</groupId>
<artifactId>killbill</artifactId>
- <version>0.0.8-SNAPSHOT</version>
+ <version>0.0.9-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-catalog</artifactId>
diff --git a/catalog/src/main/java/com/ning/billing/catalog/CaseBillingAlignment.java b/catalog/src/main/java/com/ning/billing/catalog/CaseBillingAlignment.java
index 698c5e4..064bb61 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/CaseBillingAlignment.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/CaseBillingAlignment.java
@@ -25,6 +25,7 @@ import com.ning.billing.catalog.api.ProductCategory;
public class CaseBillingAlignment extends CasePhase<BillingAlignment> {
+
@XmlElement(required=true)
private BillingAlignment alignment;
diff --git a/catalog/src/main/java/com/ning/billing/catalog/CatalogService.java b/catalog/src/main/java/com/ning/billing/catalog/CatalogService.java
index 6f04aa6..f1d01c8 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/CatalogService.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/CatalogService.java
@@ -22,6 +22,8 @@ import com.ning.billing.catalog.api.ICatalog;
import com.ning.billing.catalog.api.ICatalogService;
import com.ning.billing.config.ICatalogConfig;
import com.ning.billing.lifecycle.IService;
+import com.ning.billing.lifecycle.LyfecycleHandlerType;
+import com.ning.billing.lifecycle.LyfecycleHandlerType.LyfecycleLevel;
import com.ning.billing.util.config.XMLLoader;
public class CatalogService implements IService, Provider<ICatalog>, ICatalogService {
@@ -41,8 +43,8 @@ public class CatalogService implements IService, Provider<ICatalog>, ICatalogSer
this.isInitialized = false;
}
- @Override
- public synchronized void initialize() throws ServiceException {
+ @LyfecycleHandlerType(LyfecycleLevel.LOAD_CATALOG)
+ public synchronized void loadCatalog() throws ServiceException {
if (!isInitialized) {
try {
catalog = XMLLoader.getObjectFromProperty(config.getCatalogURI(), Catalog.class);
@@ -53,22 +55,13 @@ public class CatalogService implements IService, Provider<ICatalog>, ICatalogSer
}
}
- public String getName() {
- return CATALOG_SERVICE_NAME;
- }
-
@Override
- public void start() throws ServiceException {
- // Intentionally blank
-
+ public String getName() {
+ return CATALOG_SERVICE_NAME;
}
- @Override
- public void stop() throws ServiceException {
- // Intentionally blank
- }
/* (non-Javadoc)
* @see com.ning.billing.catalog.ICatlogService#getCatalog()
diff --git a/catalog/src/main/java/com/ning/billing/catalog/glue/CatalogModule.java b/catalog/src/main/java/com/ning/billing/catalog/glue/CatalogModule.java
index 5191977..deb2305 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/glue/CatalogModule.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/glue/CatalogModule.java
@@ -20,7 +20,9 @@ import org.skife.config.ConfigurationObjectFactory;
import com.google.inject.AbstractModule;
import com.ning.billing.catalog.CatalogService;
+import com.ning.billing.catalog.CatalogUserApi;
import com.ning.billing.catalog.api.ICatalogService;
+import com.ning.billing.catalog.api.ICatalogUserApi;
import com.ning.billing.config.ICatalogConfig;
public class CatalogModule extends AbstractModule {
@@ -30,10 +32,15 @@ public class CatalogModule extends AbstractModule {
bind(ICatalogConfig.class).toInstance(config);
}
+ protected void installCatalog() {
+ bind(ICatalogUserApi.class).to(CatalogUserApi.class).asEagerSingleton();
+ bind(ICatalogService.class).to(CatalogService.class).asEagerSingleton();
+ }
+
@Override
protected void configure() {
installConfig();
- bind(ICatalogService.class).to(CatalogService.class).asEagerSingleton();
+ installCatalog();
}
}
entitlement/pom.xml 2(+1 -1)
diff --git a/entitlement/pom.xml b/entitlement/pom.xml
index 099a4ad..e8d5e8d 100644
--- a/entitlement/pom.xml
+++ b/entitlement/pom.xml
@@ -13,7 +13,7 @@
<parent>
<groupId>com.ning.billing</groupId>
<artifactId>killbill</artifactId>
- <version>0.0.8-SNAPSHOT</version>
+ <version>0.0.9-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-entitlement</artifactId>
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/alignment/PlanAligner.java b/entitlement/src/main/java/com/ning/billing/entitlement/alignment/PlanAligner.java
index 7856dab..0d9ac8d 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/alignment/PlanAligner.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/alignment/PlanAligner.java
@@ -21,7 +21,9 @@ import java.util.List;
import org.joda.time.DateTime;
+import com.google.inject.Inject;
import com.ning.billing.catalog.api.ICatalog;
+import com.ning.billing.catalog.api.ICatalogService;
import com.ning.billing.catalog.api.IDuration;
import com.ning.billing.catalog.api.IPlan;
import com.ning.billing.catalog.api.IPlanPhase;
@@ -35,16 +37,13 @@ import com.ning.billing.util.clock.Clock;
public class PlanAligner implements IPlanAligner {
- // STEPH this is a bit broken right now until we figure out to retrieve ICatalog
- private /*final*/ ICatalog catalog;
+ private final ICatalogService catalogService;
- public PlanAligner() {
- //this.catalog = Engine.getInstance().getCatalog();
+ @Inject
+ public PlanAligner(ICatalogService catalogService) {
+ this.catalogService = catalogService;
}
- public void init(ICatalog catalog) {
- this.catalog = catalog;
- }
private enum WhichPhase {
CURRENT,
@@ -87,6 +86,8 @@ public class PlanAligner implements IPlanAligner {
private TimedPhase getTimedPhaseOnCreate(Subscription subscription,
IPlan plan, String priceList, DateTime effectiveDate, WhichPhase which) {
+ ICatalog catalog = catalogService.getCatalog();
+
PlanSpecifier planSpecifier = new PlanSpecifier(plan.getProduct().getName(),
plan.getProduct().getCategory(),
plan.getBillingPeriod(),
@@ -111,6 +112,8 @@ public class PlanAligner implements IPlanAligner {
private TimedPhase getTimedPhaseOnChange(Subscription subscription,
IPlan plan, String priceList, DateTime effectiveDate, WhichPhase which) {
+ ICatalog catalog = catalogService.getCatalog();
+
IPlanPhase currentPhase = subscription.getCurrentPhase();
IPlan currentPlan = subscription.getCurrentPlan();
String currentPriceList = subscription.getCurrentPriceList();
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/EntitlementUserApi.java b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/EntitlementUserApi.java
index c30e2c1..8561ce0 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/EntitlementUserApi.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/EntitlementUserApi.java
@@ -22,7 +22,6 @@ import java.util.UUID;
import org.joda.time.DateTime;
-import com.google.inject.Inject;
import com.ning.billing.ErrorCode;
import com.ning.billing.account.api.IAccount;
import com.ning.billing.catalog.api.BillingPeriod;
@@ -42,6 +41,7 @@ import com.ning.billing.entitlement.events.phase.IPhaseEvent;
import com.ning.billing.entitlement.events.phase.PhaseEvent;
import com.ning.billing.entitlement.events.user.ApiEventCreate;
import com.ning.billing.entitlement.exceptions.EntitlementError;
+import com.ning.billing.entitlement.glue.InjectorMagic;
import com.ning.billing.util.clock.IClock;
public class EntitlementUserApi implements IEntitlementUserApi {
@@ -68,7 +68,7 @@ public class EntitlementUserApi implements IEntitlementUserApi {
@Override
public synchronized void initialize(List<IApiListener> listeners) {
if (!initialized) {
- this.catalog = engine.getCatalog();
+ this.catalog = InjectorMagic.getCatlog();
engine.registerApiObservers(listeners);
initialized = true;
}
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/Subscription.java b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/Subscription.java
index 6e07f7c..a5cd11e 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/Subscription.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/Subscription.java
@@ -49,6 +49,7 @@ import com.ning.billing.entitlement.events.user.ApiEventType;
import com.ning.billing.entitlement.events.user.ApiEventUncancel;
import com.ning.billing.entitlement.events.user.IUserEvent;
import com.ning.billing.entitlement.exceptions.EntitlementError;
+import com.ning.billing.entitlement.glue.InjectorMagic;
import com.ning.billing.util.clock.IClock;
public class Subscription extends PrivateFields implements ISubscription {
@@ -146,12 +147,10 @@ public class Subscription extends PrivateFields implements ISubscription {
public Subscription(UUID id, UUID bundleId, ProductCategory category, DateTime bundleStartDate, DateTime startDate, DateTime ctd, DateTime ptd, long activeVersion) {
super();
-
- Engine engine = Engine.getInstance();
- this.clock = engine.getClock();
- this.dao = engine.getDao();
- this.catalog = engine.getCatalog();
- this.planAligner = engine.getPlanAligner();
+ this.clock = InjectorMagic.getClock();
+ this.dao = InjectorMagic.getEntitlementDao();
+ this.catalog = InjectorMagic.getCatlog();
+ this.planAligner = InjectorMagic.getPlanAligner();
this.id = id;
this.bundleId = bundleId;
this.startDate = startDate;
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/engine/core/Engine.java b/entitlement/src/main/java/com/ning/billing/entitlement/engine/core/Engine.java
index 0db9538..dd33ae5 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/engine/core/Engine.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/engine/core/Engine.java
@@ -17,7 +17,6 @@
package com.ning.billing.entitlement.engine.core;
import java.util.List;
-import java.util.UUID;
import org.joda.time.DateTime;
import org.slf4j.Logger;
@@ -26,14 +25,12 @@ import org.slf4j.LoggerFactory;
import com.google.inject.Inject;
import com.ning.billing.catalog.api.ICatalog;
import com.ning.billing.catalog.api.ICatalogService;
-import com.ning.billing.catalog.api.ICatalogUserApi;
-import com.ning.billing.catalog.api.IPlan;
import com.ning.billing.config.IEntitlementConfig;
-import com.ning.billing.entitlement.IEntitlementService;
import com.ning.billing.entitlement.alignment.IPlanAligner;
import com.ning.billing.entitlement.alignment.IPlanAligner.TimedPhase;
import com.ning.billing.entitlement.alignment.PlanAligner;
+import com.ning.billing.entitlement.api.IEntitlementService;
import com.ning.billing.entitlement.api.billing.BillingApi;
import com.ning.billing.entitlement.api.billing.IEntitlementBillingApi;
import com.ning.billing.entitlement.api.user.EntitlementUserApi;
@@ -46,6 +43,8 @@ import com.ning.billing.entitlement.events.IEvent.EventType;
import com.ning.billing.entitlement.events.phase.IPhaseEvent;
import com.ning.billing.entitlement.events.phase.PhaseEvent;
import com.ning.billing.entitlement.events.user.IUserEvent;
+import com.ning.billing.lifecycle.LyfecycleHandlerType;
+import com.ning.billing.lifecycle.LyfecycleHandlerType.LyfecycleLevel;
import com.ning.billing.util.clock.IClock;
public class Engine implements IEventListener, IEntitlementService {
@@ -53,34 +52,27 @@ public class Engine implements IEventListener, IEntitlementService {
private static final String ENTITLEMENT_SERVICE_NAME = "entitlement-service";
private final static Logger log = LoggerFactory.getLogger(Engine.class);
- private static Engine instance = null;
private final IClock clock;
-
private final IEntitlementDao dao;
private final IApiEventProcessor apiEventProcessor;
- private final ICatalogService catalogService;
private final IPlanAligner planAligner;
private final IEntitlementUserApi userApi;
private final IEntitlementBillingApi billingApi;
private List<IApiListener> observers;
- private ICatalog catalog;
@Inject
- public Engine(IClock clock, IEntitlementDao dao, IApiEventProcessor apiEventProcessor, ICatalogService catalogService,
+ public Engine(IClock clock, IEntitlementDao dao, IApiEventProcessor apiEventProcessor,
IPlanAligner planAligner, IEntitlementConfig config) {
super();
this.clock = clock;
this.dao = dao;
this.apiEventProcessor = apiEventProcessor;
this.planAligner = planAligner;
- this.catalogService = catalogService;
this.observers = null;
this.userApi = new EntitlementUserApi(this, clock, planAligner, dao);
this.billingApi = new BillingApi(this, clock, dao);
- instance = this;
-
}
@Override
@@ -89,20 +81,16 @@ public class Engine implements IEventListener, IEntitlementService {
}
- @Override
+ @LyfecycleHandlerType(LyfecycleLevel.INIT_SERVICE)
public void initialize() {
- this.catalog = catalogService.getCatalog();
- // STEPH yack
- ((PlanAligner) planAligner).init(catalog);
-
}
- @Override
+ @LyfecycleHandlerType(LyfecycleLevel.START_SERVICE)
public void start() {
apiEventProcessor.startNotifications(this);
}
- @Override
+ @LyfecycleHandlerType(LyfecycleLevel.STOP_SERVICE)
public void stop() {
apiEventProcessor.stopNotifications();
}
@@ -177,31 +165,4 @@ public class Engine implements IEventListener, IEntitlementService {
dao.createNextPhaseEvent(subscription.getId(), nextPhaseEvent);
}
}
-
-
- //
- // STEPH would be nice to have those go away..
- //
-
- // For non Guice classes
- public synchronized static Engine getInstance() {
- return instance;
- }
-
- public IClock getClock() {
- return clock;
- }
-
- public ICatalog getCatalog() {
- return catalog;
- }
-
- public IEntitlementDao getDao() {
- return dao;
- }
-
- public IPlanAligner getPlanAligner() {
- return planAligner;
- }
-
}
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/glue/EntitlementModule.java b/entitlement/src/main/java/com/ning/billing/entitlement/glue/EntitlementModule.java
index 6074d94..d303b30 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/glue/EntitlementModule.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/glue/EntitlementModule.java
@@ -19,12 +19,12 @@ package com.ning.billing.entitlement.glue;
import org.skife.config.ConfigurationObjectFactory;
import com.google.inject.AbstractModule;
-import com.ning.billing.catalog.CatalogUserApi;
-import com.ning.billing.catalog.api.ICatalogUserApi;
import com.ning.billing.config.IEntitlementConfig;
-import com.ning.billing.entitlement.IEntitlementService;
import com.ning.billing.entitlement.alignment.IPlanAligner;
import com.ning.billing.entitlement.alignment.PlanAligner;
+import com.ning.billing.entitlement.api.IEntitlementService;
+import com.ning.billing.entitlement.api.user.EntitlementUserApi;
+import com.ning.billing.entitlement.api.user.IEntitlementUserApi;
import com.ning.billing.entitlement.engine.core.ApiEventProcessor;
import com.ning.billing.entitlement.engine.core.Engine;
import com.ning.billing.entitlement.engine.core.IApiEventProcessor;
@@ -37,9 +37,6 @@ import com.ning.billing.util.clock.IClock;
public class EntitlementModule extends AbstractModule {
- protected void installCatalog() {
- bind(ICatalogUserApi.class).to(CatalogUserApi.class).asEagerSingleton();
- }
protected void installClock() {
bind(IClock.class).to(Clock.class).asEagerSingleton();
@@ -64,12 +61,15 @@ public class EntitlementModule extends AbstractModule {
bind(IPlanAligner.class).to(PlanAligner.class).asEagerSingleton();
}
+ protected void installInjectorMagic() {
+ bind(InjectorMagic.class).asEagerSingleton();
+ }
@Override
protected void configure() {
+ installInjectorMagic();
installConfig();
installClock();
- installCatalog();
installApiEventProcessor();
installEntitlementDao();
installEntitlementCore();
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/glue/InjectorMagic.java b/entitlement/src/main/java/com/ning/billing/entitlement/glue/InjectorMagic.java
new file mode 100644
index 0000000..8e845da
--- /dev/null
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/glue/InjectorMagic.java
@@ -0,0 +1,76 @@
+/*
+ * 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.entitlement.glue;
+
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import com.ning.billing.catalog.api.ICatalog;
+import com.ning.billing.catalog.api.ICatalogService;
+import com.ning.billing.entitlement.alignment.IPlanAligner;
+import com.ning.billing.entitlement.engine.dao.IEntitlementDao;
+import com.ning.billing.util.clock.IClock;
+
+//
+// Allows to return Guice injected singleton in a non guice context
+//
+public class InjectorMagic {
+
+ // public void testng only
+ public static InjectorMagic instance;
+
+ private final Injector injector;
+
+ @Inject
+ public InjectorMagic(Injector injector) {
+ this.injector = injector;
+ synchronized(InjectorMagic.class) {
+ if (instance == null) {
+ instance = this;
+ }
+ }
+ }
+
+
+ public static IClock getClock() {
+ return InjectorMagic.get().getInstance(IClock.class);
+ }
+
+ public static ICatalog getCatlog() {
+ ICatalogService catalogService = InjectorMagic.get().getInstance(ICatalogService.class);
+ return catalogService.getCatalog();
+ }
+
+ public static IEntitlementDao getEntitlementDao() {
+ return InjectorMagic.get().getInstance(IEntitlementDao.class);
+ }
+
+ public static IPlanAligner getPlanAligner() {
+ return InjectorMagic.get().getInstance(IPlanAligner.class);
+ }
+
+
+ public static Injector get() {
+ if (instance == null) {
+ throw new RuntimeException("Trying to retrieve injector too early");
+ }
+ return instance.getInjector();
+ }
+
+ private Injector getInjector() {
+ return injector;
+ }
+}
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiBase.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiBase.java
index 13786fb..4c2ae2b 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiBase.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiBase.java
@@ -36,23 +36,26 @@ import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testng.Assert;
+import org.testng.annotations.AfterClass;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.BeforeSuite;
+import org.testng.annotations.BeforeTest;
import com.google.inject.Injector;
import com.ning.billing.account.api.IAccount;
+import com.ning.billing.catalog.CatalogService;
import com.ning.billing.catalog.api.BillingPeriod;
import com.ning.billing.catalog.api.Currency;
import com.ning.billing.catalog.api.ICatalog;
import com.ning.billing.catalog.api.ICatalogService;
-import com.ning.billing.catalog.api.ICatalogUserApi;
import com.ning.billing.catalog.api.IDuration;
import com.ning.billing.catalog.api.TimeUnit;
import com.ning.billing.config.IEntitlementConfig;
-import com.ning.billing.entitlement.IEntitlementService;
import com.ning.billing.entitlement.api.ApiTestListener;
import com.ning.billing.entitlement.api.ApiTestListener.NextEvent;
+import com.ning.billing.entitlement.api.IEntitlementService;
import com.ning.billing.entitlement.api.billing.IEntitlementBillingApi;
import com.ning.billing.entitlement.engine.core.Engine;
import com.ning.billing.entitlement.engine.dao.IEntitlementDao;
@@ -61,6 +64,7 @@ import com.ning.billing.entitlement.events.IEvent;
import com.ning.billing.entitlement.events.phase.IPhaseEvent;
import com.ning.billing.entitlement.events.user.ApiEventType;
import com.ning.billing.entitlement.events.user.IUserEvent;
+import com.ning.billing.entitlement.glue.InjectorMagic;
import com.ning.billing.lifecycle.IService.ServiceException;
import com.ning.billing.util.clock.ClockMock;
import com.ning.billing.util.clock.IClock;
@@ -72,7 +76,6 @@ public abstract class TestUserApiBase {
protected static final long DAY_IN_MS = (24 * 3600 * 1000);
protected IEntitlementService entitlementService;
- //protected Engine engine;
protected IEntitlementUserApi entitlementApi;
protected IEntitlementBillingApi billingApi;
protected ICatalogService catalogService;
@@ -85,6 +88,7 @@ public abstract class TestUserApiBase {
protected ApiTestListener testListener;
protected ISubscriptionBundle bundle;
+ private InjectorMagic injectorMagic;
public static void loadSystemPropertiesFromClasspath( final String resource )
{
@@ -98,20 +102,20 @@ public abstract class TestUserApiBase {
}
}
+ @AfterClass(groups={"setup"})
+ public void tearDown() {
+ InjectorMagic.instance = null;
+ }
@BeforeClass(groups={"setup"})
public void setup() {
- // Does not see to work ...
- /*
- TimeZone tz = TimeZone.getDefault();
- TimeZone.setDefault(TimeZone.getTimeZone("Etc/UTC"));
- tz = TimeZone.getDefault();
- */
-
loadSystemPropertiesFromClasspath("/entitlement.properties");
final Injector g = getInjector();
+ injectorMagic = g.getInstance(InjectorMagic.class);
+
+
entitlementService = g.getInstance(IEntitlementService.class);
catalogService = g.getInstance(ICatalogService.class);
config = g.getInstance(IEntitlementConfig.class);
@@ -119,13 +123,12 @@ public abstract class TestUserApiBase {
clock = (ClockMock) g.getInstance(IClock.class);
try {
- catalogService.initialize();
- entitlementService.initialize();
+ ((CatalogService) catalogService).loadCatalog();
+ ((Engine)entitlementService).initialize();
init();
} catch (EntitlementUserApiException e) {
Assert.fail(e.getMessage());
} catch (ServiceException e) {
- e.printStackTrace();
Assert.fail(e.getMessage());
}
}
@@ -149,33 +152,29 @@ public abstract class TestUserApiBase {
@BeforeMethod(groups={"setup"})
public void setupTest() {
+
+ log.warn("\n");
+ log.warn("RESET TEST FRAMEWORK\n\n");
+
+ testListener.reset();
+ clock.resetDeltaFromReality();
+ ((IEntitlementDaoMock) dao).reset();
try {
- log.warn("\n");
- log.warn("RESET TEST FRAMEWORK\n\n");
-
- testListener.reset();
- clock.resetDeltaFromReality();
- ((IEntitlementDaoMock) dao).reset();
- try {
- bundle = entitlementApi.createBundleForAccount(account, "myDefaultBundle");
- } catch (EntitlementUserApiException e) {
- Assert.fail(e.getMessage());
- }
- assertNotNull(bundle);
- entitlementService.start();
- } catch (ServiceException e) {
+ bundle = entitlementApi.createBundleForAccount(account, "myDefaultBundle");
+ } catch (EntitlementUserApiException e) {
Assert.fail(e.getMessage());
}
+ assertNotNull(bundle);
+
+ ((Engine)entitlementService).start();
}
@AfterMethod(groups={"setup"})
public void cleanupTest() {
- try {
- entitlementService.stop();
- log.warn("DONE WITH TEST\n");
- } catch (ServiceException e) {
- Assert.fail(e.getMessage());
- }
+
+
+ ((Engine)entitlementService).stop();
+ log.warn("DONE WITH TEST\n");
}
// Glue magic to invoke the real test
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCancel.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCancel.java
index 05e5432..24468fe 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCancel.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCancel.java
@@ -44,7 +44,7 @@ public abstract class TestUserApiCancel extends TestUserApiBase {
protected void testCancelSubscriptionIMMReal() {
- log.info("Starting testChangeSubscriptionEOTWithNoChargeThroughDate");
+ log.info("Starting testCancelSubscriptionIMM");
try {
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCancelMemory.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCancelMemory.java
index 896c592..00c2bab 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCancelMemory.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCancelMemory.java
@@ -16,7 +16,6 @@
package com.ning.billing.entitlement.api.user;
-import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import com.google.inject.Guice;
@@ -30,7 +29,7 @@ public class TestUserApiCancelMemory extends TestUserApiCancel {
@Override
protected Injector getInjector() {
- return Guice.createInjector(Stage.DEVELOPMENT, new EngineModuleMemoryMock(), new CatalogModuleMock());
+ return Guice.createInjector(Stage.PRODUCTION, new EngineModuleMemoryMock(), new CatalogModuleMock());
}
@Test(enabled=true, groups={"fast"})
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiChangePlan.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiChangePlan.java
index 4def199..f187d9f 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiChangePlan.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiChangePlan.java
@@ -74,7 +74,7 @@ public abstract class TestUserApiChangePlan extends TestUserApiBase {
private void tChangePlanBundleAlignEOTWithNoChargeThroughDate(String fromProd, BillingPeriod fromTerm, String fromPlanSet,
String toProd, BillingPeriod toTerm, String toPlanSet) {
- log.info("Starting testChangeSubscriptionEOTWithNoChargeThroughDate");
+ log.info("Starting testChangePlanBundleAlignEOTWithNoChargeThroughDateReal");
try {
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiChangePlanMemory.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiChangePlanMemory.java
index acb5e69..4455436 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiChangePlanMemory.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiChangePlanMemory.java
@@ -28,7 +28,7 @@ public class TestUserApiChangePlanMemory extends TestUserApiChangePlan {
@Override
protected Injector getInjector() {
- return Guice.createInjector(Stage.DEVELOPMENT, new EngineModuleMemoryMock(), new CatalogModuleMock());
+ return Guice.createInjector(Stage.PRODUCTION, new EngineModuleMemoryMock(), new CatalogModuleMock());
}
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCreateMemory.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCreateMemory.java
index 1c119f8..429652c 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCreateMemory.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCreateMemory.java
@@ -29,7 +29,7 @@ public class TestUserApiCreateMemory extends TestUserApiCreate {
@Override
protected Injector getInjector() {
- return Guice.createInjector(Stage.DEVELOPMENT, new EngineModuleMemoryMock(), new CatalogModuleMock());
+ return Guice.createInjector(Stage.PRODUCTION, new EngineModuleMemoryMock(), new CatalogModuleMock());
}
@Test(enabled=true, groups={"fast"})
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/glue/CatalogModuleMock.java b/entitlement/src/test/java/com/ning/billing/entitlement/glue/CatalogModuleMock.java
index 565a854..3b24fe8 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/glue/CatalogModuleMock.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/glue/CatalogModuleMock.java
@@ -20,4 +20,5 @@ import com.ning.billing.catalog.glue.CatalogModule;
public class CatalogModuleMock extends CatalogModule {
+
}
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/glue/EngineModuleMemoryMock.java b/entitlement/src/test/java/com/ning/billing/entitlement/glue/EngineModuleMemoryMock.java
index e930cb2..3a701cc 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/glue/EngineModuleMemoryMock.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/glue/EngineModuleMemoryMock.java
@@ -17,21 +17,12 @@
package com.ning.billing.entitlement.glue;
-import org.skife.config.ConfigurationObjectFactory;
-import org.skife.jdbi.v2.DBI;
-
-import com.ning.billing.dbi.DBIProvider;
-import com.ning.billing.dbi.DbiConfig;
import com.ning.billing.entitlement.engine.core.ApiEventProcessorMemoryMock;
import com.ning.billing.entitlement.engine.core.IApiEventProcessor;
import com.ning.billing.entitlement.engine.dao.EntitlementDaoMemoryMock;
import com.ning.billing.entitlement.engine.dao.IEntitlementDao;
-import com.ning.billing.entitlement.glue.EntitlementModule;
-import com.ning.billing.util.clock.ClockMock;
-import com.ning.billing.util.clock.IClock;
-
-public class EngineModuleMemoryMock extends EntitlementModule {
+public class EngineModuleMemoryMock extends EngineModuleMock {
@Override
protected void installApiEventProcessor() {
bind(IApiEventProcessor.class).to(ApiEventProcessorMemoryMock.class).asEagerSingleton();
@@ -42,20 +33,9 @@ public class EngineModuleMemoryMock extends EntitlementModule {
bind(IEntitlementDao.class).to(EntitlementDaoMemoryMock.class).asEagerSingleton();
}
- @Override
- protected void installClock() {
- bind(IClock.class).to(ClockMock.class).asEagerSingleton();
- }
-
- protected void installDBI() {
- bind(DBI.class).toProvider(DBIProvider.class).asEagerSingleton();
- final DbiConfig config = new ConfigurationObjectFactory(System.getProperties()).build(DbiConfig.class);
- bind(DbiConfig.class).toInstance(config);
- }
@Override
protected void configure() {
super.configure();
- installDBI();
}
}
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/glue/EngineModuleMock.java b/entitlement/src/test/java/com/ning/billing/entitlement/glue/EngineModuleMock.java
new file mode 100644
index 0000000..d70a2f7
--- /dev/null
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/glue/EngineModuleMock.java
@@ -0,0 +1,34 @@
+/*
+ * 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.entitlement.glue;
+
+import com.ning.billing.util.clock.ClockMock;
+import com.ning.billing.util.clock.IClock;
+
+public class EngineModuleMock extends EntitlementModule {
+
+ @Override
+ protected void installClock() {
+ bind(IClock.class).to(ClockMock.class).asEagerSingleton();
+ }
+
+ @Override
+ protected void configure() {
+ super.configure();
+ }
+
+}
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/glue/EngineModuleSqlMock.java b/entitlement/src/test/java/com/ning/billing/entitlement/glue/EngineModuleSqlMock.java
index 6fdc8e5..9dd1c2d 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/glue/EngineModuleSqlMock.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/glue/EngineModuleSqlMock.java
@@ -26,7 +26,7 @@ import com.ning.billing.entitlement.engine.dao.IEntitlementDao;
import com.ning.billing.util.clock.ClockMock;
import com.ning.billing.util.clock.IClock;
-public class EngineModuleSqlMock extends EntitlementModule {
+public class EngineModuleSqlMock extends EngineModuleMock {
@Override
invoice/pom.xml 2(+1 -1)
diff --git a/invoice/pom.xml b/invoice/pom.xml
index e29e10a..cd4a90a 100644
--- a/invoice/pom.xml
+++ b/invoice/pom.xml
@@ -13,7 +13,7 @@
<parent>
<groupId>com.ning.billing</groupId>
<artifactId>killbill</artifactId>
- <version>0.0.8-SNAPSHOT</version>
+ <version>0.0.9-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-invoice</artifactId>
payment/pom.xml 2(+1 -1)
diff --git a/payment/pom.xml b/payment/pom.xml
index ac9488b..a4278d1 100644
--- a/payment/pom.xml
+++ b/payment/pom.xml
@@ -13,7 +13,7 @@
<parent>
<groupId>com.ning.billing</groupId>
<artifactId>killbill</artifactId>
- <version>0.0.8-SNAPSHOT</version>
+ <version>0.0.9-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-payment</artifactId>
pom.xml 7(+6 -1)
diff --git a/pom.xml b/pom.xml
index 8223f0a..0333fc8 100644
--- a/pom.xml
+++ b/pom.xml
@@ -17,7 +17,7 @@
<groupId>com.ning.billing</groupId>
<artifactId>killbill</artifactId>
<packaging>pom</packaging>
- <version>0.0.8-SNAPSHOT</version>
+ <version>0.0.9-SNAPSHOT</version>
<name>killbill</name>
<description>Library for managing recurring subscriptions and the associated billing</description>
<url>http://github.com/sbrossie/killbill</url>
@@ -56,6 +56,11 @@
</dependency>
<dependency>
<groupId>com.ning.billing</groupId>
+ <artifactId>killbill-entitlement</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>com.ning.billing</groupId>
<artifactId>killbill-catalog</artifactId>
<version>${project.version}</version>
</dependency>
util/pom.xml 2(+1 -1)
diff --git a/util/pom.xml b/util/pom.xml
index 9aa0bc8..5d4542b 100644
--- a/util/pom.xml
+++ b/util/pom.xml
@@ -13,7 +13,7 @@
<parent>
<groupId>com.ning.billing</groupId>
<artifactId>killbill</artifactId>
- <version>0.0.8-SNAPSHOT</version>
+ <version>0.0.9-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>killbill-util</artifactId>