mirror of https://github.com/apache/jclouds.git
Issue 61: refactored core S3 to allow different error handling and xml parsing
git-svn-id: http://jclouds.googlecode.com/svn/trunk@1428 3d8758e0-26b5-11de-8745-db77d3ebf521
This commit is contained in:
parent
ac8210c90a
commit
09ba1d1360
|
@ -44,6 +44,7 @@ import java.util.Properties;
|
|||
import org.jclouds.aws.s3.config.LiveS3ConnectionModule;
|
||||
import org.jclouds.aws.s3.config.S3ConnectionModule;
|
||||
import org.jclouds.aws.s3.config.S3ContextModule;
|
||||
import org.jclouds.aws.s3.xml.config.S3ParserModule;
|
||||
import org.jclouds.http.config.HttpFutureCommandClientModule;
|
||||
import org.jclouds.http.config.JavaUrlHttpFutureCommandClientModule;
|
||||
import org.jclouds.logging.config.LoggingModule;
|
||||
|
@ -87,8 +88,10 @@ public class S3ContextFactory {
|
|||
public static S3ContextFactory createContext(String awsAccessKeyId, String awsSecretAccessKey) {
|
||||
Properties properties = new Properties();
|
||||
|
||||
properties.setProperty(PROPERTY_AWS_ACCESSKEYID, checkNotNull(awsAccessKeyId, "awsAccessKeyId"));
|
||||
properties.setProperty(PROPERTY_AWS_SECRETACCESSKEY, checkNotNull(awsSecretAccessKey,"awsSecretAccessKey"));
|
||||
properties.setProperty(PROPERTY_AWS_ACCESSKEYID, checkNotNull(awsAccessKeyId,
|
||||
"awsAccessKeyId"));
|
||||
properties.setProperty(PROPERTY_AWS_SECRETACCESSKEY, checkNotNull(awsSecretAccessKey,
|
||||
"awsSecretAccessKey"));
|
||||
|
||||
properties.setProperty(PROPERTY_HTTP_ADDRESS, "s3.amazonaws.com");
|
||||
properties.setProperty(PROPERTY_HTTP_SECURE, "true");
|
||||
|
@ -108,72 +111,51 @@ public class S3ContextFactory {
|
|||
|
||||
public static Injector createInjector(String awsAccessKeyId, String awsSecretAccessKey,
|
||||
Module... modules) {
|
||||
return createContext(awsAccessKeyId, awsSecretAccessKey)
|
||||
.withModules(modules)
|
||||
return createContext(awsAccessKeyId, awsSecretAccessKey).withModules(modules)
|
||||
.createInjector();
|
||||
}
|
||||
|
||||
public static S3Context createS3Context(String awsAccessKeyId, String awsSecretAccessKey,
|
||||
Module... modules) {
|
||||
return createContext(awsAccessKeyId, awsSecretAccessKey)
|
||||
.withModules(modules)
|
||||
.build();
|
||||
return createContext(awsAccessKeyId, awsSecretAccessKey).withModules(modules).build();
|
||||
|
||||
}
|
||||
|
||||
public static Injector createInjector(String awsAccessKeyId, String awsSecretAccessKey,
|
||||
boolean isSecure, Module... modules) {
|
||||
return createContext(awsAccessKeyId, awsSecretAccessKey)
|
||||
.withModules(modules)
|
||||
.withHttpSecure(isSecure)
|
||||
.createInjector();
|
||||
return createContext(awsAccessKeyId, awsSecretAccessKey).withModules(modules).withHttpSecure(
|
||||
isSecure).createInjector();
|
||||
}
|
||||
|
||||
public static S3Context createS3Context(String awsAccessKeyId, String awsSecretAccessKey,
|
||||
boolean isSecure, Module... modules) {
|
||||
|
||||
return createContext(awsAccessKeyId, awsSecretAccessKey)
|
||||
.withModules(modules)
|
||||
.withHttpSecure(isSecure)
|
||||
.build();
|
||||
return createContext(awsAccessKeyId, awsSecretAccessKey).withModules(modules).withHttpSecure(
|
||||
isSecure).build();
|
||||
}
|
||||
|
||||
public static Injector createInjector(String awsAccessKeyId, String awsSecretAccessKey,
|
||||
boolean isSecure, String server, Module... modules) {
|
||||
return createContext(awsAccessKeyId, awsSecretAccessKey)
|
||||
.withModules(modules)
|
||||
.withHttpSecure(isSecure)
|
||||
.withHttpAddress(server)
|
||||
.createInjector();
|
||||
return createContext(awsAccessKeyId, awsSecretAccessKey).withModules(modules).withHttpSecure(
|
||||
isSecure).withHttpAddress(server).createInjector();
|
||||
}
|
||||
|
||||
public static S3Context createS3Context(String awsAccessKeyId, String awsSecretAccessKey,
|
||||
boolean isSecure, String server, Module... modules) {
|
||||
return createContext(awsAccessKeyId, awsSecretAccessKey)
|
||||
.withModules(modules)
|
||||
.withHttpSecure(isSecure)
|
||||
.withHttpAddress(server)
|
||||
.build();
|
||||
return createContext(awsAccessKeyId, awsSecretAccessKey).withModules(modules).withHttpSecure(
|
||||
isSecure).withHttpAddress(server).build();
|
||||
}
|
||||
|
||||
public static S3Context createS3Context(String awsAccessKeyId, String awsSecretAccessKey,
|
||||
boolean isSecure, String server, int port, Module... modules) {
|
||||
return createContext(awsAccessKeyId, awsSecretAccessKey)
|
||||
.withModules(modules)
|
||||
.withHttpSecure(isSecure)
|
||||
.withHttpAddress(server)
|
||||
.withHttpPort(port)
|
||||
.build();
|
||||
return createContext(awsAccessKeyId, awsSecretAccessKey).withModules(modules).withHttpSecure(
|
||||
isSecure).withHttpAddress(server).withHttpPort(port).build();
|
||||
}
|
||||
|
||||
public static Injector createInjector(String awsAccessKeyId, String awsSecretAccessKey,
|
||||
boolean isSecure, String server, int port, Module... modules) {
|
||||
return createContext(awsAccessKeyId, awsSecretAccessKey)
|
||||
.withModules(modules)
|
||||
.withHttpSecure(isSecure)
|
||||
.withHttpAddress(server)
|
||||
.withHttpPort(port)
|
||||
.createInjector();
|
||||
return createContext(awsAccessKeyId, awsSecretAccessKey).withModules(modules).withHttpSecure(
|
||||
isSecure).withHttpAddress(server).withHttpPort(port).createInjector();
|
||||
}
|
||||
|
||||
public S3ContextFactory withHttpAddress(String httpAddress) {
|
||||
|
@ -197,25 +179,29 @@ public class S3ContextFactory {
|
|||
}
|
||||
|
||||
public S3ContextFactory withPoolMaxConnectionReuse(int poolMaxConnectionReuse) {
|
||||
properties.setProperty(PROPERTY_POOL_MAX_CONNECTION_REUSE, Integer.toString(poolMaxConnectionReuse));
|
||||
properties.setProperty(PROPERTY_POOL_MAX_CONNECTION_REUSE, Integer
|
||||
.toString(poolMaxConnectionReuse));
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
public S3ContextFactory withPoolMaxSessionFailures(int poolMaxSessionFailures) {
|
||||
properties.setProperty(PROPERTY_POOL_MAX_SESSION_FAILURES, Integer.toString(poolMaxSessionFailures));
|
||||
properties.setProperty(PROPERTY_POOL_MAX_SESSION_FAILURES, Integer
|
||||
.toString(poolMaxSessionFailures));
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
public S3ContextFactory withPoolRequestInvokerThreads(int poolRequestInvokerThreads) {
|
||||
properties.setProperty(PROPERTY_POOL_REQUEST_INVOKER_THREADS, Integer.toString(poolRequestInvokerThreads));
|
||||
properties.setProperty(PROPERTY_POOL_REQUEST_INVOKER_THREADS, Integer
|
||||
.toString(poolRequestInvokerThreads));
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
public S3ContextFactory withPoolIoWorkerThreads(int poolIoWorkerThreads) {
|
||||
properties.setProperty(PROPERTY_POOL_IO_WORKER_THREADS, Integer.toString(poolIoWorkerThreads));
|
||||
properties
|
||||
.setProperty(PROPERTY_POOL_IO_WORKER_THREADS, Integer.toString(poolIoWorkerThreads));
|
||||
return this;
|
||||
|
||||
}
|
||||
|
@ -237,8 +223,8 @@ public class S3ContextFactory {
|
|||
|
||||
private Injector createInjector() {
|
||||
/* Use 80 or 443 as the default port if one hasn't been set? */
|
||||
if(!properties.containsKey(PROPERTY_HTTP_PORT)) {
|
||||
if(Boolean.parseBoolean(properties.getProperty(PROPERTY_HTTP_SECURE))) {
|
||||
if (!properties.containsKey(PROPERTY_HTTP_PORT)) {
|
||||
if (Boolean.parseBoolean(properties.getProperty(PROPERTY_HTTP_SECURE))) {
|
||||
properties.setProperty(PROPERTY_HTTP_PORT, DEFAULT_SECURE_HTTP_PORT);
|
||||
} else {
|
||||
properties.setProperty(PROPERTY_HTTP_PORT, DEFAULT_NON_SECURE_HTTP_PORT);
|
||||
|
@ -248,6 +234,8 @@ public class S3ContextFactory {
|
|||
|
||||
addLoggingModuleIfNotPresent(modules);
|
||||
|
||||
addS3ParserModuleIfNotPresent(modules);
|
||||
|
||||
addS3ConnectionModuleIfNotPresent(modules);
|
||||
|
||||
addHttpModuleIfNeededAndNotPresent(modules);
|
||||
|
@ -262,6 +250,16 @@ public class S3ContextFactory {
|
|||
}, new S3ContextModule());
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
static void addS3ParserModuleIfNotPresent(List<Module> modules) {
|
||||
if (!Iterables.any(modules, new Predicate<Module>() {
|
||||
public boolean apply(Module input) {
|
||||
return input instanceof S3ParserModule;
|
||||
}
|
||||
|
||||
}))
|
||||
modules.add(new S3ParserModule());
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
static void addHttpModuleIfNeededAndNotPresent(final List<Module> modules) {
|
||||
|
|
|
@ -31,7 +31,6 @@ import org.jclouds.aws.s3.commands.HeadObject;
|
|||
import org.jclouds.aws.s3.commands.PutBucket;
|
||||
import org.jclouds.aws.s3.commands.PutObject;
|
||||
import org.jclouds.aws.s3.commands.S3CommandFactory;
|
||||
import org.jclouds.aws.s3.xml.config.S3ParserModule;
|
||||
|
||||
import com.google.inject.AbstractModule;
|
||||
import com.google.inject.assistedinject.FactoryProvider;
|
||||
|
@ -44,41 +43,36 @@ import com.google.inject.assistedinject.FactoryProvider;
|
|||
public class S3CommandsModule extends AbstractModule {
|
||||
@Override
|
||||
protected void configure() {
|
||||
install(new S3ParserModule());
|
||||
|
||||
bind(S3CommandFactory.DeleteBucketFactory.class).toProvider(
|
||||
FactoryProvider.newFactory(
|
||||
S3CommandFactory.DeleteBucketFactory.class,
|
||||
FactoryProvider.newFactory(S3CommandFactory.DeleteBucketFactory.class,
|
||||
DeleteBucket.class));
|
||||
|
||||
bind(S3CommandFactory.DeleteObjectFactory.class).toProvider(
|
||||
FactoryProvider.newFactory(
|
||||
S3CommandFactory.DeleteObjectFactory.class,
|
||||
FactoryProvider.newFactory(S3CommandFactory.DeleteObjectFactory.class,
|
||||
DeleteObject.class));
|
||||
|
||||
bind(S3CommandFactory.BucketExistsFactory.class).toProvider(
|
||||
FactoryProvider.newFactory(
|
||||
S3CommandFactory.BucketExistsFactory.class,
|
||||
FactoryProvider.newFactory(S3CommandFactory.BucketExistsFactory.class,
|
||||
BucketExists.class));
|
||||
|
||||
bind(S3CommandFactory.PutBucketFactory.class).toProvider(
|
||||
FactoryProvider.newFactory(
|
||||
S3CommandFactory.PutBucketFactory.class,
|
||||
bind(S3CommandFactory.PutBucketFactory.class)
|
||||
.toProvider(
|
||||
FactoryProvider.newFactory(S3CommandFactory.PutBucketFactory.class,
|
||||
PutBucket.class));
|
||||
|
||||
bind(S3CommandFactory.PutObjectFactory.class).toProvider(
|
||||
FactoryProvider.newFactory(
|
||||
S3CommandFactory.PutObjectFactory.class,
|
||||
bind(S3CommandFactory.PutObjectFactory.class)
|
||||
.toProvider(
|
||||
FactoryProvider.newFactory(S3CommandFactory.PutObjectFactory.class,
|
||||
PutObject.class));
|
||||
|
||||
bind(S3CommandFactory.GetObjectFactory.class).toProvider(
|
||||
FactoryProvider.newFactory(
|
||||
S3CommandFactory.GetObjectFactory.class,
|
||||
bind(S3CommandFactory.GetObjectFactory.class)
|
||||
.toProvider(
|
||||
FactoryProvider.newFactory(S3CommandFactory.GetObjectFactory.class,
|
||||
GetObject.class));
|
||||
|
||||
bind(S3CommandFactory.HeadMetadataFactory.class).toProvider(
|
||||
FactoryProvider.newFactory(
|
||||
S3CommandFactory.HeadMetadataFactory.class,
|
||||
FactoryProvider.newFactory(S3CommandFactory.HeadMetadataFactory.class,
|
||||
HeadObject.class));
|
||||
|
||||
}
|
||||
|
|
|
@ -73,17 +73,22 @@ public class LiveS3ConnectionModule extends AbstractModule {
|
|||
|
||||
@Override
|
||||
protected void configure() {
|
||||
bindResponseHandlers();
|
||||
|
||||
bind(S3Connection.class).to(LiveS3Connection.class).in(Scopes.SINGLETON);
|
||||
bind(HttpRetryHandler.class).annotatedWith(RetryHandler.class).to(
|
||||
BackoffLimitedRetryHandler.class).in(Scopes.SINGLETON);
|
||||
requestInjection(this);
|
||||
logger.info("S3 Context = %1$s://%2$s:%3$s", (isSecure ? "https" : "http"), address, port);
|
||||
}
|
||||
|
||||
protected void bindResponseHandlers() {
|
||||
bind(HttpResponseHandler.class).annotatedWith(RedirectHandler.class).to(
|
||||
CloseContentAndSetExceptionHandler.class).in(Scopes.SINGLETON);
|
||||
bind(HttpResponseHandler.class).annotatedWith(ClientErrorHandler.class).to(
|
||||
ParseAWSErrorFromXmlContent.class).in(Scopes.SINGLETON);
|
||||
bind(HttpResponseHandler.class).annotatedWith(ServerErrorHandler.class).to(
|
||||
ParseAWSErrorFromXmlContent.class).in(Scopes.SINGLETON);
|
||||
bind(HttpRetryHandler.class).annotatedWith(RetryHandler.class).to(
|
||||
BackoffLimitedRetryHandler.class).in(Scopes.SINGLETON);
|
||||
requestInjection(this);
|
||||
logger.info("S3 Context = %1$s://%2$s:%3$s", (isSecure ? "https" : "http"), address, port);
|
||||
}
|
||||
|
||||
@Provides
|
||||
|
|
|
@ -48,34 +48,30 @@ import com.google.inject.assistedinject.FactoryProvider;
|
|||
* @author Adrian Cole
|
||||
*/
|
||||
public class S3ParserModule extends AbstractModule {
|
||||
private final TypeLiteral<S3ParserFactory.GenericParseFactory
|
||||
<List<S3Bucket.Metadata>>> listBucketsTypeLiteral =
|
||||
new TypeLiteral<S3ParserFactory.GenericParseFactory<List<S3Bucket.Metadata>>>() {
|
||||
protected final TypeLiteral<S3ParserFactory.GenericParseFactory<AWSError>> errorTypeLiteral = new TypeLiteral<S3ParserFactory.GenericParseFactory<AWSError>>() {
|
||||
};
|
||||
private final TypeLiteral<S3ParserFactory.GenericParseFactory
|
||||
<S3Bucket>> bucketTypeLiteral =
|
||||
new TypeLiteral<S3ParserFactory.GenericParseFactory<S3Bucket>>() {
|
||||
protected final TypeLiteral<S3ParserFactory.GenericParseFactory<List<S3Bucket.Metadata>>> listBucketsTypeLiteral = new TypeLiteral<S3ParserFactory.GenericParseFactory<List<S3Bucket.Metadata>>>() {
|
||||
};
|
||||
private final TypeLiteral<S3ParserFactory.GenericParseFactory
|
||||
<S3Object.Metadata>> objectMetadataTypeLiteral =
|
||||
new TypeLiteral<S3ParserFactory.GenericParseFactory<S3Object.Metadata>>() {
|
||||
protected final TypeLiteral<S3ParserFactory.GenericParseFactory<S3Bucket>> bucketTypeLiteral = new TypeLiteral<S3ParserFactory.GenericParseFactory<S3Bucket>>() {
|
||||
};
|
||||
private final TypeLiteral<S3ParserFactory.GenericParseFactory
|
||||
<AWSError>> errorTypeLiteral =
|
||||
new TypeLiteral<S3ParserFactory.GenericParseFactory<AWSError>>() {
|
||||
protected final TypeLiteral<S3ParserFactory.GenericParseFactory<S3Object.Metadata>> objectMetadataTypeLiteral = new TypeLiteral<S3ParserFactory.GenericParseFactory<S3Object.Metadata>>() {
|
||||
};
|
||||
private final TypeLiteral<S3ParserFactory.GenericParseFactory
|
||||
<AccessControlList>> accessControlListTypeLiteral =
|
||||
new TypeLiteral<S3ParserFactory.GenericParseFactory<AccessControlList>>() {
|
||||
protected final TypeLiteral<S3ParserFactory.GenericParseFactory<AccessControlList>> accessControlListTypeLiteral = new TypeLiteral<S3ParserFactory.GenericParseFactory<AccessControlList>>() {
|
||||
};
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
install(new SaxModule());
|
||||
bindErrorHandler();
|
||||
bindCallablesThatReturnParseResults();
|
||||
bindParserImplementationsToReturnTypes();
|
||||
}
|
||||
|
||||
protected void bindErrorHandler() {
|
||||
bind(new TypeLiteral<ParseSax.HandlerWithResult<AWSError>>() {
|
||||
}).to(ErrorHandler.class);
|
||||
}
|
||||
|
||||
private void bindParserImplementationsToReturnTypes() {
|
||||
bind(new TypeLiteral<ParseSax.HandlerWithResult<List<S3Bucket.Metadata>>>() {
|
||||
}).to(ListAllMyBucketsHandler.class);
|
||||
|
@ -83,8 +79,6 @@ public class S3ParserModule extends AbstractModule {
|
|||
}).to(ListBucketHandler.class);
|
||||
bind(new TypeLiteral<ParseSax.HandlerWithResult<S3Object.Metadata>>() {
|
||||
}).to(CopyObjectHandler.class);
|
||||
bind(new TypeLiteral<ParseSax.HandlerWithResult<AWSError>>() {
|
||||
}).to(ErrorHandler.class);
|
||||
bind(new TypeLiteral<ParseSax.HandlerWithResult<AccessControlList>>() {
|
||||
}).to(AccessControlListHandler.class);
|
||||
}
|
||||
|
@ -101,12 +95,13 @@ public class S3ParserModule extends AbstractModule {
|
|||
FactoryProvider.newFactory(objectMetadataTypeLiteral,
|
||||
new TypeLiteral<ParseSax<S3Object.Metadata>>() {
|
||||
}));
|
||||
bind(accessControlListTypeLiteral).toProvider(
|
||||
FactoryProvider.newFactory(accessControlListTypeLiteral,
|
||||
new TypeLiteral<ParseSax<AccessControlList>>() {
|
||||
}));
|
||||
bind(errorTypeLiteral).toProvider(
|
||||
FactoryProvider.newFactory(errorTypeLiteral, new TypeLiteral<ParseSax<AWSError>>() {
|
||||
}));
|
||||
bind(accessControlListTypeLiteral).toProvider(
|
||||
FactoryProvider.newFactory(accessControlListTypeLiteral,
|
||||
new TypeLiteral<ParseSax<AccessControlList>>() {}));
|
||||
}
|
||||
|
||||
}
|
|
@ -35,6 +35,7 @@ import org.jclouds.aws.s3.commands.options.PutBucketOptions;
|
|||
import org.jclouds.aws.s3.commands.options.PutObjectOptions;
|
||||
import org.jclouds.aws.s3.domain.S3Object;
|
||||
import org.jclouds.aws.s3.domain.S3Bucket.Metadata.LocationConstraint;
|
||||
import org.jclouds.aws.s3.xml.config.S3ParserModule;
|
||||
import org.testng.annotations.AfterTest;
|
||||
import org.testng.annotations.BeforeTest;
|
||||
import org.testng.annotations.Test;
|
||||
|
@ -56,7 +57,7 @@ public class S3CommandFactoryTest {
|
|||
|
||||
@BeforeTest
|
||||
void setUpInjector() {
|
||||
injector = Guice.createInjector(new S3CommandsModule() {
|
||||
injector = Guice.createInjector(new S3ParserModule(), new S3CommandsModule() {
|
||||
@Override
|
||||
protected void configure() {
|
||||
bindConstant().annotatedWith(Names.named("jclouds.http.address")).to("localhost");
|
||||
|
|
|
@ -27,6 +27,7 @@ import static org.testng.Assert.assertEquals;
|
|||
|
||||
import org.jclouds.aws.s3.handlers.ParseAWSErrorFromXmlContent;
|
||||
import org.jclouds.aws.s3.reference.S3Constants;
|
||||
import org.jclouds.aws.s3.xml.config.S3ParserModule;
|
||||
import org.jclouds.http.HttpResponseHandler;
|
||||
import org.jclouds.http.HttpRetryHandler;
|
||||
import org.jclouds.http.annotation.ClientErrorHandler;
|
||||
|
@ -50,18 +51,24 @@ import com.google.inject.name.Names;
|
|||
public class S3ContextModuleTest {
|
||||
|
||||
Injector createInjector() {
|
||||
return Guice.createInjector(new LiveS3ConnectionModule(), new S3ContextModule() {
|
||||
return Guice.createInjector(new LiveS3ConnectionModule(), new S3ParserModule(),
|
||||
new S3ContextModule() {
|
||||
@Override
|
||||
protected void configure() {
|
||||
bindConstant().annotatedWith(Names.named(S3Constants.PROPERTY_AWS_ACCESSKEYID)).to(
|
||||
bindConstant()
|
||||
.annotatedWith(Names.named(S3Constants.PROPERTY_AWS_ACCESSKEYID)).to(
|
||||
"localhost");
|
||||
bindConstant().annotatedWith(Names.named(S3Constants.PROPERTY_AWS_SECRETACCESSKEY)).to(
|
||||
"localhost");
|
||||
bindConstant().annotatedWith(Names.named(S3Constants.PROPERTY_HTTP_ADDRESS)).to(
|
||||
"localhost");
|
||||
bindConstant().annotatedWith(Names.named(S3Constants.PROPERTY_HTTP_PORT)).to("1000");
|
||||
bindConstant().annotatedWith(Names.named(S3Constants.PROPERTY_HTTP_SECURE)).to("false");
|
||||
bindConstant().annotatedWith(Names.named(S3Constants.PROPERTY_HTTP_MAX_RETRIES)).to("5");
|
||||
bindConstant().annotatedWith(
|
||||
Names.named(S3Constants.PROPERTY_AWS_SECRETACCESSKEY))
|
||||
.to("localhost");
|
||||
bindConstant().annotatedWith(Names.named(S3Constants.PROPERTY_HTTP_ADDRESS))
|
||||
.to("localhost");
|
||||
bindConstant().annotatedWith(Names.named(S3Constants.PROPERTY_HTTP_PORT)).to(
|
||||
"1000");
|
||||
bindConstant().annotatedWith(Names.named(S3Constants.PROPERTY_HTTP_SECURE))
|
||||
.to("false");
|
||||
bindConstant().annotatedWith(
|
||||
Names.named(S3Constants.PROPERTY_HTTP_MAX_RETRIES)).to("5");
|
||||
super.configure();
|
||||
}
|
||||
}, new JavaUrlHttpFutureCommandClientModule());
|
||||
|
|
Loading…
Reference in New Issue