Details
diff --git a/azkaban-common/src/main/java/azkaban/AzkabanCommonModule.java b/azkaban-common/src/main/java/azkaban/AzkabanCommonModule.java
index f528556..71fb6b9 100644
--- a/azkaban-common/src/main/java/azkaban/AzkabanCommonModule.java
+++ b/azkaban-common/src/main/java/azkaban/AzkabanCommonModule.java
@@ -25,7 +25,6 @@ import azkaban.db.DatabaseOperator;
import azkaban.db.DatabaseOperatorImpl;
import azkaban.db.H2FileDataSource;
import azkaban.db.MySQLDataSource;
-import azkaban.executor.AlerterHolder;
import azkaban.executor.ExecutorLoader;
import azkaban.executor.ExecutorManager;
import azkaban.executor.JdbcExecutorLoader;
@@ -76,16 +75,13 @@ public class AzkabanCommonModule extends AbstractModule {
@Override
protected void configure() {
- bind(ExecutorLoader.class).to(JdbcExecutorLoader.class).in(Scopes.SINGLETON);
bind(Props.class).toInstance(this.config.getProps());
- bind(Storage.class).to(resolveStorageClassType()).in(Scopes.SINGLETON);
- bind(HdfsAuth.class).in(Scopes.SINGLETON);
- bind(DatabaseOperator.class).to(DatabaseOperatorImpl.class).in(Scopes.SINGLETON);
- bind(TriggerLoader.class).to(JdbcTriggerImpl.class).in(Scopes.SINGLETON);
- bind(ProjectLoader.class).to(JdbcProjectImpl.class).in(Scopes.SINGLETON);
+ bind(Storage.class).to(resolveStorageClassType());
+ bind(DatabaseOperator.class).to(DatabaseOperatorImpl.class);
+ bind(TriggerLoader.class).to(JdbcTriggerImpl.class);
+ bind(ProjectLoader.class).to(JdbcProjectImpl.class);
bind(DataSource.class).to(AzkabanDataSource.class);
- bind(ExecutorManager.class).in(Scopes.SINGLETON);
- bind(AlerterHolder.class).in(Scopes.SINGLETON);
+ bind(ExecutorLoader.class).to(JdbcExecutorLoader.class);
bind(MetricRegistry.class).in(Scopes.SINGLETON);
}
diff --git a/azkaban-common/src/main/java/azkaban/executor/AlerterHolder.java b/azkaban-common/src/main/java/azkaban/executor/AlerterHolder.java
index 9c3d799..95c2347 100644
--- a/azkaban-common/src/main/java/azkaban/executor/AlerterHolder.java
+++ b/azkaban-common/src/main/java/azkaban/executor/AlerterHolder.java
@@ -23,6 +23,7 @@ import azkaban.utils.FileIOUtils;
import azkaban.utils.Props;
import azkaban.utils.PropsUtils;
import com.google.inject.Inject;
+import com.google.inject.Singleton;
import java.io.File;
import java.lang.reflect.Constructor;
import java.net.MalformedURLException;
@@ -36,6 +37,7 @@ import java.util.Map;
import org.apache.log4j.Logger;
+@Singleton
public class AlerterHolder {
private static final Logger logger = Logger.getLogger(AlerterHolder.class);
diff --git a/azkaban-common/src/main/java/azkaban/executor/ExecutorManager.java b/azkaban-common/src/main/java/azkaban/executor/ExecutorManager.java
index 9c0a032..e5328be 100644
--- a/azkaban-common/src/main/java/azkaban/executor/ExecutorManager.java
+++ b/azkaban-common/src/main/java/azkaban/executor/ExecutorManager.java
@@ -21,6 +21,7 @@ import azkaban.metrics.CommonMetrics;
import azkaban.utils.FlowUtils;
import com.google.common.collect.Lists;
import com.google.inject.Inject;
+import com.google.inject.Singleton;
import java.io.File;
import java.io.IOException;
import java.lang.Thread.State;
@@ -68,6 +69,7 @@ import azkaban.utils.Props;
* Executor manager used to manage the client side job.
*
*/
+@Singleton
public class ExecutorManager extends EventHandler implements
ExecutorManagerAdapter {
static final String AZKABAN_EXECUTOR_SELECTOR_FILTERS =
diff --git a/azkaban-common/src/main/java/azkaban/executor/JdbcExecutorLoader.java b/azkaban-common/src/main/java/azkaban/executor/JdbcExecutorLoader.java
index 2f7b9cf..0e572a7 100644
--- a/azkaban-common/src/main/java/azkaban/executor/JdbcExecutorLoader.java
+++ b/azkaban-common/src/main/java/azkaban/executor/JdbcExecutorLoader.java
@@ -18,6 +18,7 @@ package azkaban.executor;
import azkaban.metrics.CommonMetrics;
import com.google.inject.Inject;
+import com.google.inject.Singleton;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
@@ -54,6 +55,7 @@ import azkaban.utils.Pair;
import azkaban.utils.Props;
import azkaban.utils.PropsUtils;
+@Singleton
public class JdbcExecutorLoader extends AbstractJdbcLoader implements
ExecutorLoader {
private static final Logger logger = Logger
diff --git a/azkaban-common/src/main/java/azkaban/project/JdbcProjectImpl.java b/azkaban-common/src/main/java/azkaban/project/JdbcProjectImpl.java
index b212a92..8e28396 100644
--- a/azkaban-common/src/main/java/azkaban/project/JdbcProjectImpl.java
+++ b/azkaban-common/src/main/java/azkaban/project/JdbcProjectImpl.java
@@ -41,6 +41,7 @@ import azkaban.utils.PropsUtils;
import azkaban.utils.Triple;
import com.google.common.io.Files;
import com.google.inject.Inject;
+import com.google.inject.Singleton;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
@@ -62,6 +63,7 @@ import org.apache.log4j.Logger;
* TODO kunkun-tang: This class is too long. In future, we should split {@link ProjectLoader} interface
* and have multiple short class implementations.
*/
+@Singleton
public class JdbcProjectImpl implements ProjectLoader {
private static final Logger logger = Logger.getLogger(JdbcProjectImpl.class);
diff --git a/azkaban-common/src/main/java/azkaban/storage/DatabaseStorage.java b/azkaban-common/src/main/java/azkaban/storage/DatabaseStorage.java
index 6622da0..7c6b15e 100644
--- a/azkaban-common/src/main/java/azkaban/storage/DatabaseStorage.java
+++ b/azkaban-common/src/main/java/azkaban/storage/DatabaseStorage.java
@@ -21,6 +21,7 @@ import azkaban.project.ProjectFileHandler;
import azkaban.project.ProjectLoader;
import azkaban.spi.Storage;
import azkaban.spi.StorageMetadata;
+import com.google.inject.Singleton;
import java.io.File;
import java.io.InputStream;
import javax.inject.Inject;
@@ -32,6 +33,7 @@ import javax.inject.Inject;
* This class helps in storing projects in the DB itself. This is intended to be the default since
* it is the current behavior of Azkaban.
*/
+@Singleton
public class DatabaseStorage implements Storage {
private final ProjectLoader projectLoader;
diff --git a/azkaban-common/src/main/java/azkaban/storage/HdfsAuth.java b/azkaban-common/src/main/java/azkaban/storage/HdfsAuth.java
index 6a56b50..b9a666d 100644
--- a/azkaban-common/src/main/java/azkaban/storage/HdfsAuth.java
+++ b/azkaban-common/src/main/java/azkaban/storage/HdfsAuth.java
@@ -24,6 +24,7 @@ import static java.util.Objects.requireNonNull;
import azkaban.spi.AzkabanException;
import azkaban.utils.Props;
import com.google.inject.Inject;
+import com.google.inject.Singleton;
import java.io.IOException;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.security.UserGroupInformation;
@@ -34,6 +35,7 @@ import org.apache.log4j.Logger;
* This class helps in HDFS authorization and is a wrapper over Hadoop's {@link
* UserGroupInformation} class.
*/
+@Singleton
public class HdfsAuth {
private static final Logger log = Logger.getLogger(HdfsAuth.class);
diff --git a/azkaban-common/src/main/java/azkaban/storage/HdfsStorage.java b/azkaban-common/src/main/java/azkaban/storage/HdfsStorage.java
index d2d374f..b0ef27e 100644
--- a/azkaban-common/src/main/java/azkaban/storage/HdfsStorage.java
+++ b/azkaban-common/src/main/java/azkaban/storage/HdfsStorage.java
@@ -25,6 +25,7 @@ import azkaban.spi.Storage;
import azkaban.spi.StorageException;
import azkaban.spi.StorageMetadata;
import com.google.inject.Inject;
+import com.google.inject.Singleton;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
@@ -35,6 +36,7 @@ import org.apache.hadoop.fs.Path;
import org.apache.log4j.Logger;
+@Singleton
public class HdfsStorage implements Storage {
private static final Logger log = Logger.getLogger(HdfsStorage.class);
diff --git a/azkaban-common/src/main/java/azkaban/storage/LocalStorage.java b/azkaban-common/src/main/java/azkaban/storage/LocalStorage.java
index 21adef5..56d4143 100644
--- a/azkaban-common/src/main/java/azkaban/storage/LocalStorage.java
+++ b/azkaban-common/src/main/java/azkaban/storage/LocalStorage.java
@@ -25,6 +25,7 @@ import azkaban.spi.StorageException;
import azkaban.spi.StorageMetadata;
import azkaban.utils.FileIOUtils;
import com.google.inject.Inject;
+import com.google.inject.Singleton;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
@@ -34,6 +35,7 @@ import org.apache.commons.io.FileUtils;
import org.apache.log4j.Logger;
+@Singleton
public class LocalStorage implements Storage {
private static final Logger log = Logger.getLogger(LocalStorage.class);
diff --git a/azkaban-common/src/main/java/azkaban/trigger/JdbcTriggerImpl.java b/azkaban-common/src/main/java/azkaban/trigger/JdbcTriggerImpl.java
index 1d25215..aa442bd 100644
--- a/azkaban-common/src/main/java/azkaban/trigger/JdbcTriggerImpl.java
+++ b/azkaban-common/src/main/java/azkaban/trigger/JdbcTriggerImpl.java
@@ -22,6 +22,7 @@ import azkaban.db.SQLTransaction;
import azkaban.utils.GZIPUtils;
import azkaban.utils.JSONUtils;
import com.google.inject.Inject;
+import com.google.inject.Singleton;
import java.io.IOException;
import java.sql.ResultSet;
import java.sql.SQLException;
@@ -33,6 +34,7 @@ import org.apache.log4j.Logger;
import org.joda.time.DateTime;
+@Singleton
public class JdbcTriggerImpl implements TriggerLoader {
private static final String TRIGGER_TABLE_NAME = "triggers";
diff --git a/azkaban-common/src/test/java/azkaban/ServiceProviderTest.java b/azkaban-common/src/test/java/azkaban/ServiceProviderTest.java
index ac3d6bd..d401660 100644
--- a/azkaban-common/src/test/java/azkaban/ServiceProviderTest.java
+++ b/azkaban-common/src/test/java/azkaban/ServiceProviderTest.java
@@ -18,7 +18,7 @@
package azkaban;
import static azkaban.ServiceProvider.SERVICE_PROVIDER;
-import static org.junit.Assert.assertNotNull;
+import static org.assertj.core.api.Assertions.assertThat;
import azkaban.db.DatabaseOperator;
import azkaban.project.JdbcProjectImpl;
@@ -39,6 +39,15 @@ public class ServiceProviderTest {
public static final String AZKABAN_LOCAL_TEST_STORAGE = "AZKABAN_LOCAL_TEST_STORAGE";
+ // Test if one class is singletonly guiced. could be called by
+ // AZ Common, Web, or Exec Modules.
+ public static void assertSingleton(final Class azkabanClass, final Injector injector) {
+ final Object azkabanObj1 = injector.getInstance(azkabanClass);
+ final Object azkabanObj2 = injector.getInstance(azkabanClass);
+ // Note: isSameAs is quite different from isEqualto in AssertJ
+ assertThat(azkabanObj1).isSameAs(azkabanObj2).isNotNull();
+ }
+
@After
public void tearDown() throws Exception {
FileUtils.deleteDirectory(new File(AZKABAN_LOCAL_TEST_STORAGE));
@@ -58,11 +67,11 @@ public class ServiceProviderTest {
SERVICE_PROVIDER.unsetInjector();
SERVICE_PROVIDER.setInjector(injector);
- assertNotNull(SERVICE_PROVIDER.getInstance(JdbcProjectImpl.class));
- assertNotNull(SERVICE_PROVIDER.getInstance(StorageManager.class));
- assertNotNull(SERVICE_PROVIDER.getInstance(DatabaseStorage.class));
- assertNotNull(SERVICE_PROVIDER.getInstance(LocalStorage.class));
- assertNotNull(SERVICE_PROVIDER.getInstance(Storage.class));
- assertNotNull(SERVICE_PROVIDER.getInstance(DatabaseOperator.class));
+ assertThat(injector.getInstance(JdbcProjectImpl.class)).isNotNull();
+ assertThat(injector.getInstance(StorageManager.class)).isNotNull();
+ assertThat(injector.getInstance(DatabaseStorage.class)).isNotNull();
+ assertThat(injector.getInstance(LocalStorage.class)).isNotNull();
+ assertThat(injector.getInstance(Storage.class)).isNotNull();
+ assertThat(injector.getInstance(DatabaseOperator.class)).isNotNull();
}
}
diff --git a/azkaban-db/src/main/java/azkaban/db/DatabaseOperatorImpl.java b/azkaban-db/src/main/java/azkaban/db/DatabaseOperatorImpl.java
index 556a534..9a89eda 100644
--- a/azkaban-db/src/main/java/azkaban/db/DatabaseOperatorImpl.java
+++ b/azkaban-db/src/main/java/azkaban/db/DatabaseOperatorImpl.java
@@ -18,6 +18,7 @@ package azkaban.db;
import static java.util.Objects.requireNonNull;
import com.google.inject.Inject;
+import com.google.inject.Singleton;
import java.sql.Connection;
import java.sql.SQLException;
import org.apache.commons.dbutils.DbUtils;
@@ -28,6 +29,7 @@ import org.apache.log4j.Logger;
/**
* Implement AZ DB related operations. This class is thread safe.
*/
+@Singleton
public class DatabaseOperatorImpl implements DatabaseOperator {
private static final Logger logger = Logger.getLogger(DatabaseOperatorImpl.class);
diff --git a/azkaban-exec-server/src/main/java/azkaban/execapp/AzkabanExecServerModule.java b/azkaban-exec-server/src/main/java/azkaban/execapp/AzkabanExecServerModule.java
index 1688705..fc47a15 100644
--- a/azkaban-exec-server/src/main/java/azkaban/execapp/AzkabanExecServerModule.java
+++ b/azkaban-exec-server/src/main/java/azkaban/execapp/AzkabanExecServerModule.java
@@ -32,7 +32,7 @@ public class AzkabanExecServerModule extends AbstractModule {
@Override
protected void configure() {
- bind(ExecutorLoader.class).to(JdbcExecutorLoader.class).in(Scopes.SINGLETON);
+ bind(ExecutorLoader.class).to(JdbcExecutorLoader.class);
bind(AzkabanExecutorServer.class).in(Scopes.SINGLETON);
bind(TriggerManager.class).in(Scopes.SINGLETON);
bind(FlowRunnerManager.class).in(Scopes.SINGLETON);
diff --git a/azkaban-web-server/src/test/java/azkaban/webapp/AzkabanWebServerTest.java b/azkaban-web-server/src/test/java/azkaban/webapp/AzkabanWebServerTest.java
index 4f17833..a4ef1a0 100644
--- a/azkaban-web-server/src/test/java/azkaban/webapp/AzkabanWebServerTest.java
+++ b/azkaban-web-server/src/test/java/azkaban/webapp/AzkabanWebServerTest.java
@@ -18,17 +18,23 @@
package azkaban.webapp;
import static azkaban.ServiceProvider.SERVICE_PROVIDER;
+import static azkaban.ServiceProviderTest.assertSingleton;
import static azkaban.executor.ExecutorManager.AZKABAN_USE_MULTIPLE_EXECUTORS;
import static java.util.Objects.requireNonNull;
import static org.apache.commons.io.FileUtils.deleteQuietly;
import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
import azkaban.AzkabanCommonModule;
import azkaban.database.AzkabanDatabaseSetup;
import azkaban.database.AzkabanDatabaseUpdater;
+import azkaban.db.DatabaseOperator;
import azkaban.executor.Executor;
import azkaban.executor.ExecutorLoader;
+import azkaban.executor.ExecutorManager;
+import azkaban.project.ProjectLoader;
+import azkaban.project.ProjectManager;
+import azkaban.spi.Storage;
+import azkaban.trigger.TriggerLoader;
import azkaban.trigger.TriggerManager;
import azkaban.utils.Props;
import com.google.inject.Guice;
@@ -115,9 +121,15 @@ public class AzkabanWebServerTest {
assertNotNull(injector.getInstance(AzkabanWebServer.class));
//Test if triggermanager is singletonly guiced. If not, the below test will fail.
- final TriggerManager triggerManager1 = requireNonNull(injector.getInstance(TriggerManager.class));
- final TriggerManager triggerManager2 = requireNonNull(injector.getInstance(TriggerManager.class));
- assertTrue(triggerManager1 == triggerManager2);
+ assertSingleton(ExecutorLoader.class, injector);
+ assertSingleton(ExecutorManager.class, injector);
+ assertSingleton(ProjectLoader.class, injector);
+ assertSingleton(ProjectManager.class, injector);
+ assertSingleton(Storage.class, injector);
+ assertSingleton(DatabaseOperator.class, injector);
+ assertSingleton(TriggerLoader.class, injector);
+ assertSingleton(TriggerManager.class, injector);
+
SERVICE_PROVIDER.unsetInjector();
}
}