feat(gateway) Rework AsyncInitialize to be more robust and function in all registries.
RENAME
gateway/platforms/vertx3/vertx3-common/src/main/java/io/apiman/gateway/platforms/vertx3/common/AsyncInitialize.java
gateway/engine/core/src/main/java/io/apiman/gateway/engine/async/AsyncInitialize.java
* limitations under the License.
*/
-package io.apiman.gateway.platforms.vertx3.common;
-
-import io.apiman.gateway.engine.async.IAsyncResultHandler;
+package io.apiman.gateway.engine.async;
/**
* @author Marc Savy {@literal <marc@rhymewithgravy.com>}

MODIFY
gateway/engine/core/src/main/java/io/apiman/gateway/engine/impl/AbstractEngineFactory.java
gateway/engine/core/src/main/java/io/apiman/gateway/engine/impl/AbstractEngineFactory.java
@@ -66,6 +66,7 @@ public abstract class AbstractEngineFactory implements IEngineFactory {
initializer.initialize();
}
+ complete();
return new EngineImpl(registry, pluginRegistry, componentRegistry, cfactory, pfactory, metrics, logFactory, pathParser);
}
@@ -138,4 +139,9 @@ public abstract class AbstractEngineFactory implements IEngineFactory {
*/
protected abstract IApiRequestPathParser createRequestPathParser(IPluginRegistry pluginRegistry);
+ /**
+ * Call when the engine factory has completed initial startup/loading..
+ */
+ protected abstract void complete();
+
}

MODIFY
gateway/engine/core/src/main/java/io/apiman/gateway/engine/impl/ConfigDrivenEngineFactory.java
gateway/engine/core/src/main/java/io/apiman/gateway/engine/impl/ConfigDrivenEngineFactory.java
@@ -26,6 +26,9 @@ import io.apiman.gateway.engine.IGatewayInitializer;
import io.apiman.gateway.engine.IMetrics;
import io.apiman.gateway.engine.IPluginRegistry;
import io.apiman.gateway.engine.IRegistry;
+import io.apiman.gateway.engine.async.AsyncInitialize;
+import io.apiman.gateway.engine.async.AsyncResultImpl;
+import io.apiman.gateway.engine.async.IAsyncResultHandler;
import io.apiman.gateway.engine.policy.IPolicyFactory;
import java.lang.reflect.Constructor;
@@ -41,6 +44,10 @@ import java.util.Map;
public class ConfigDrivenEngineFactory extends AbstractEngineFactory {
private IEngineConfig engineConfig;
+ private IAsyncResultHandler<Void> handler;
+ private boolean failed;
+ private int asyncInitializeAwaiting;
+ private boolean finishedLoading;
/**
* Constructor.
@@ -169,6 +176,47 @@ public class ConfigDrivenEngineFactory extends AbstractEngineFactory {
* @return a new instance of 'type'
*/
protected <T> T create(Class<T> type, Map<String, String> config) {
+ // Use #doInstantiate so inheriting classes can override it, as #instantiate is static final.
+ T instance = doInstantiate(type, config);
+
+ if (instance instanceof AsyncInitialize) {
+ asyncInitializeAwaiting += 1;
+ ((AsyncInitialize) instance).initialize(initResult -> {
+ if (initResult.isError()) {
+ if (!failed) { // Not already failed before
+ failed = true;
+ if (handler != null)
+ handler.handle(initResult);
+ } else {
+ System.err.println("Failure occurred, but error handler was already invoked: " + initResult.getError().getCause()); //$NON-NLS-1$
+ }
+ } else {
+ asyncInitializeAwaiting -= 1;
+ checkLoadingStatus();
+ }
+ });
+ }
+
+ checkLoadingStatus();
+ return instance;
+ }
+
+ protected void checkLoadingStatus() {
+ if (handler != null && !failed && finishedLoading && asyncInitializeAwaiting == 0) {
+ handler.handle(AsyncResultImpl.create((Void) null));
+ }
+ }
+
+ protected IAsyncResultHandler<Void> getResultHandler() {
+ return handler;
+ }
+
+ public AbstractEngineFactory setResultHandler(IAsyncResultHandler<Void> handler) {
+ this.handler = handler;
+ return this;
+ }
+
+ protected <T> T doInstantiate(Class<T> type, Map<String, String> config) {
return instantiate(type, config);
}
@@ -194,4 +242,10 @@ public class ConfigDrivenEngineFactory extends AbstractEngineFactory {
}
}
+ @Override
+ protected void complete() {
+ finishedLoading = true;
+ checkLoadingStatus();
+ }
+
}

MODIFY
gateway/engine/core/src/main/java/io/apiman/gateway/engine/impl/DefaultEngineFactory.java
gateway/engine/core/src/main/java/io/apiman/gateway/engine/impl/DefaultEngineFactory.java
@@ -18,6 +18,7 @@ package io.apiman.gateway.engine.impl;
import io.apiman.common.logging.DefaultDelegateFactory;
import io.apiman.common.logging.IDelegateFactory;
import io.apiman.common.util.crypt.IDataEncrypter;
+import io.apiman.gateway.engine.IApiRequestPathParser;
import io.apiman.gateway.engine.IComponentRegistry;
import io.apiman.gateway.engine.IGatewayInitializer;
import io.apiman.gateway.engine.IMetrics;
@@ -113,4 +114,9 @@ public abstract class DefaultEngineFactory extends AbstractEngineFactory {
protected IDelegateFactory createLoggerFactory(IPluginRegistry pluginRegistry) {
return new DefaultDelegateFactory();
}
+
+ @Override
+ protected IApiRequestPathParser createRequestPathParser(IPluginRegistry pluginRegistry) {
+ return new DefaultRequestPathParser(Collections.emptyMap());
+ }
}

MODIFY
gateway/engine/core/src/test/java/io/apiman/gateway/engine/impl/DefaultEngineFactoryTest.java
gateway/engine/core/src/test/java/io/apiman/gateway/engine/impl/DefaultEngineFactoryTest.java
@@ -184,7 +184,6 @@ public class DefaultEngineFactoryTest {
@Override
protected IDelegateFactory createLoggerFactory(IPluginRegistry pluginRegistry) {
- // TODO Auto-generated method stub
return null;
}
@@ -192,6 +191,10 @@ public class DefaultEngineFactoryTest {
protected IApiRequestPathParser createRequestPathParser(IPluginRegistry pluginRegistry) {
return new DefaultRequestPathParser(null);
}
+
+ @Override
+ protected void complete() {
+ }
};
IEngine engine = factory.createEngine();

MODIFY
gateway/engine/vertx-polling/src/main/java/io/apiman/gateway/engine/vertx/polling/ThreeScaleURILoadingRegistry.java
gateway/engine/vertx-polling/src/main/java/io/apiman/gateway/engine/vertx/polling/ThreeScaleURILoadingRegistry.java
@@ -18,6 +18,7 @@ package io.apiman.gateway.engine.vertx.polling;
import io.apiman.gateway.engine.IEngineConfig;
import io.apiman.gateway.engine.Version;
+import io.apiman.gateway.engine.async.AsyncInitialize;
import io.apiman.gateway.engine.async.AsyncResultImpl;
import io.apiman.gateway.engine.async.IAsyncHandler;
import io.apiman.gateway.engine.async.IAsyncResultHandler;
@@ -32,7 +33,6 @@ import io.apiman.gateway.engine.vertx.polling.fetchers.threescale.beans.Content;
import io.apiman.gateway.engine.vertx.polling.fetchers.threescale.beans.ProxyConfigRoot;
import io.apiman.gateway.engine.vertx.polling.fetchers.threescale.beans.Service;
import io.apiman.gateway.engine.vertx.polling.fetchers.threescale.beans.ServicesRoot;
-import io.apiman.gateway.platforms.vertx3.common.AsyncInitialize;
import io.apiman.gateway.platforms.vertx3.common.verticles.Json;
import io.vertx.core.CompositeFuture;
import io.vertx.core.Future;

MODIFY
gateway/engine/vertx-polling/src/main/java/io/apiman/gateway/engine/vertx/polling/URILoadingRegistry.java
gateway/engine/vertx-polling/src/main/java/io/apiman/gateway/engine/vertx/polling/URILoadingRegistry.java
package io.apiman.gateway.engine.vertx.polling;
import io.apiman.gateway.engine.IEngineConfig;
+import io.apiman.gateway.engine.async.AsyncInitialize;
import io.apiman.gateway.engine.async.AsyncResultImpl;
import io.apiman.gateway.engine.async.IAsyncHandler;
import io.apiman.gateway.engine.async.IAsyncResultHandler;
@@ -28,7 +29,6 @@ import io.apiman.gateway.engine.vertx.polling.fetchers.AccessTokenResourceFetche
import io.apiman.gateway.engine.vertx.polling.fetchers.FileResourceFetcher;
import io.apiman.gateway.engine.vertx.polling.fetchers.HttpResourceFetcher;
import io.apiman.gateway.engine.vertx.polling.fetchers.ResourceFetcher;
-import io.apiman.gateway.platforms.vertx3.common.AsyncInitialize;
import io.apiman.gateway.platforms.vertx3.common.verticles.Json;
import io.vertx.core.Vertx;
import io.vertx.core.buffer.Buffer;

MODIFY
gateway/platforms/vertx3/vertx3/src/main/java/io/apiman/gateway/platforms/vertx3/engine/VertxConfigDrivenEngineFactory.java
gateway/platforms/vertx3/vertx3/src/main/java/io/apiman/gateway/platforms/vertx3/engine/VertxConfigDrivenEngineFactory.java
@@ -19,16 +19,10 @@ import io.apiman.gateway.engine.IComponentRegistry;
import io.apiman.gateway.engine.IConnectorFactory;
import io.apiman.gateway.engine.IEngineConfig;
import io.apiman.gateway.engine.IPluginRegistry;
-import io.apiman.gateway.engine.async.AsyncResultImpl;
-import io.apiman.gateway.engine.async.IAsyncResultHandler;
-import io.apiman.gateway.engine.impl.AbstractEngineFactory;
import io.apiman.gateway.engine.impl.ConfigDrivenEngineFactory;
-import io.apiman.gateway.platforms.vertx3.common.AsyncInitialize;
import io.apiman.gateway.platforms.vertx3.common.config.VertxEngineConfig;
import io.apiman.gateway.platforms.vertx3.connector.ConnectorFactory;
import io.vertx.core.Vertx;
-import io.vertx.core.logging.Logger;
-import io.vertx.core.logging.LoggerFactory;
import java.lang.reflect.Constructor;
import java.util.Map;
@@ -43,12 +37,6 @@ import java.util.Map;
public class VertxConfigDrivenEngineFactory extends ConfigDrivenEngineFactory {
private Vertx vertx;
private VertxEngineConfig vxConfig;
- private IAsyncResultHandler<Void> handler;
- private int started = 0;
- private static final int ELEMENTS_TO_START = 7; // TODO calculate elem count.
- private boolean failed = false;
- private Logger log = LoggerFactory.getLogger(VertxConfigDrivenEngineFactory.class);
-
public VertxConfigDrivenEngineFactory(Vertx vertx, VertxEngineConfig config) {
super(config);
@@ -66,30 +54,10 @@ public class VertxConfigDrivenEngineFactory extends ConfigDrivenEngineFactory {
return new VertxConfigDrivenComponentRegistry(pluginRegistry, vertx, vxConfig);
}
+ // NB: We can't override static parent version of instantiate.
@Override
- protected <T> T create(Class<T> type, Map<String, String> mapConfig) {
- started +=1;
- T instance = getInstance(type, mapConfig);
- if (instance instanceof AsyncInitialize) {
- ((AsyncInitialize) instance).initialize(initResult -> {
- if (initResult.isError()) {
- if (!failed) {
- handler.handle(initResult);
- failed = true;
- } else {
- log.error("Failure occurred, but error handler was already invoked.", initResult.getError().getCause()); //$NON-NLS-1$
- }
- }
- });
- }
- if (started == ELEMENTS_TO_START && !failed) {
- handler.handle(AsyncResultImpl.create((Void) null));
- }
- return instance;
- }
-
@SuppressWarnings("nls")
- private <T> T getInstance(Class<T> type, Map<String, String> mapConfig) {
+ protected <T> T doInstantiate(Class<T> type, Map<String, String> mapConfig) {
try {
Constructor<T> constructor = type.getConstructor(Vertx.class, VertxEngineConfig.class, Map.class);
return constructor.newInstance(vertx, vxConfig, mapConfig);
@@ -117,9 +85,4 @@ public class VertxConfigDrivenEngineFactory extends ConfigDrivenEngineFactory {
e.getMessage()), e);
}
}
-
- public AbstractEngineFactory setHandler(IAsyncResultHandler<Void> handler) {
- this.handler = handler;
- return this;
- }
}

MODIFY
gateway/platforms/vertx3/vertx3/src/main/java/io/apiman/gateway/platforms/vertx3/verticles/ApimanVerticleWithEngine.java
gateway/platforms/vertx3/vertx3/src/main/java/io/apiman/gateway/platforms/vertx3/verticles/ApimanVerticleWithEngine.java
@@ -32,7 +32,7 @@ public abstract class ApimanVerticleWithEngine extends ApimanVerticleBase {
public void start(Future<Void> startFuture) {
super.start(startFuture);
engine = new VertxConfigDrivenEngineFactory(vertx, getEngineConfig())
- .setHandler(result -> {
+ .setResultHandler(result -> {
if (result.isSuccess()) {
startFuture.complete();
} else {

MODIFY
test/policies/src/main/java/io/apiman/test/policies/PolicyTester.java
test/policies/src/main/java/io/apiman/test/policies/PolicyTester.java
@@ -17,7 +17,6 @@ package io.apiman.test.policies;
import io.apiman.common.plugin.Plugin;
import io.apiman.common.plugin.PluginCoordinates;
-import io.apiman.gateway.engine.IApiRequestPathParser;
import io.apiman.gateway.engine.IComponentRegistry;
import io.apiman.gateway.engine.IConnectorFactory;
import io.apiman.gateway.engine.IEngine;
@@ -31,7 +30,6 @@ import io.apiman.gateway.engine.components.IBufferFactoryComponent;
import io.apiman.gateway.engine.impl.ByteBufferFactoryComponent;
import io.apiman.gateway.engine.impl.DefaultComponentRegistry;
import io.apiman.gateway.engine.impl.DefaultEngineFactory;
-import io.apiman.gateway.engine.impl.DefaultRequestPathParser;
import io.apiman.gateway.engine.policy.IPolicy;
import java.io.IOException;
@@ -65,8 +63,8 @@ public class PolicyTester extends BlockJUnit4ClassRunner {
/**
* Constructor.
- * @param testClass
- * @throws InitializationError
+ * @param testClass the test class
+ * @throws InitializationError initializationerror if error on init
*/
public PolicyTester(Class<?> testClass) throws InitializationError {
super(testClass);
@@ -252,8 +250,7 @@ public class PolicyTester extends BlockJUnit4ClassRunner {
}
@Override
- protected IApiRequestPathParser createRequestPathParser(IPluginRegistry pluginRegistry) {
- return new DefaultRequestPathParser(null);
+ protected void complete() {
}
};
return factory.createEngine();

feat(gateway) Rework AsyncInitialize to be more robust and function in all registries.