diff --git a/rd-api-client/src/main/java/org/rundeck/client/RundeckClient.java b/rd-api-client/src/main/java/org/rundeck/client/RundeckClient.java
index 8048f900..a5c9b28b 100644
--- a/rd-api-client/src/main/java/org/rundeck/client/RundeckClient.java
+++ b/rd-api-client/src/main/java/org/rundeck/client/RundeckClient.java
@@ -16,6 +16,7 @@
package org.rundeck.client;
+import okhttp3.Cache;
import okhttp3.HttpUrl;
import okhttp3.JavaNetCookieJar;
import okhttp3.OkHttpClient;
@@ -294,10 +295,11 @@ private Client buildRundeckClient() {
okhttp.addInterceptor(new StaticHeaderInterceptor("User-Agent", userAgent));
+ OkHttpClient okhttp = this.okhttp.build();
- Retrofit build = new Retrofit.Builder()
+ Retrofit retrofit = new Retrofit.Builder()
.baseUrl(apiBaseUrl)
- .client(okhttp.build())
+ .client(okhttp)
.addConverterFactory(new QualifiedTypeConverterFactory(
JacksonConverterFactory.create(),
JaxbConverterFactory.create(),
@@ -306,8 +308,16 @@ private Client buildRundeckClient() {
.build();
return new Client<>(
- build.create(api),
- build,
+ retrofit.create(api),
+ retrofit,
+ () -> {
+ okhttp.dispatcher().executorService().shutdown();
+ okhttp.connectionPool().evictAll();
+ Cache cache = okhttp.cache();
+ if (null != cache && !cache.isClosed()) {
+ cache.close();
+ }
+ },
appBaseUrl,
apiBaseUrl,
usedApiVers,
diff --git a/rd-api-client/src/main/java/org/rundeck/client/util/Client.java b/rd-api-client/src/main/java/org/rundeck/client/util/Client.java
index 780b75fa..9bafaafb 100644
--- a/rd-api-client/src/main/java/org/rundeck/client/util/Client.java
+++ b/rd-api-client/src/main/java/org/rundeck/client/util/Client.java
@@ -60,6 +60,7 @@ public class Client implements ServiceClient {
private final String apiBaseUrl;
private final boolean allowVersionDowngrade;
private final Logger logger;
+ private final Closeable closer;
public interface Logger {
void output(String out);
@@ -86,6 +87,33 @@ public Client(
this.apiVersion = apiVersion;
this.allowVersionDowngrade = allowVersionDowngrade;
this.logger = logger;
+ this.closer = () -> {
+ };
+ }
+ public Client(
+ final T service,
+ final Retrofit retrofit,
+ final Closeable closer,
+ final String appBaseUrl,
+ final String apiBaseUrl,
+ final int apiVersion,
+ final boolean allowVersionDowngrade,
+ final Logger logger
+ )
+ {
+ this.service = service;
+ this.retrofit = retrofit;
+ this.appBaseUrl = appBaseUrl;
+ this.apiBaseUrl = apiBaseUrl;
+ this.apiVersion = apiVersion;
+ this.allowVersionDowngrade = allowVersionDowngrade;
+ this.logger = logger;
+ this.closer = closer;
+ }
+
+ @Override
+ public void close() throws IOException {
+ closer.close();
}
/**
diff --git a/rd-api-client/src/main/java/org/rundeck/client/util/ServiceClient.java b/rd-api-client/src/main/java/org/rundeck/client/util/ServiceClient.java
index f5ab288a..64e86901 100644
--- a/rd-api-client/src/main/java/org/rundeck/client/util/ServiceClient.java
+++ b/rd-api-client/src/main/java/org/rundeck/client/util/ServiceClient.java
@@ -7,6 +7,7 @@
import retrofit2.Response;
import retrofit2.Retrofit;
+import java.io.Closeable;
import java.io.IOException;
import java.util.function.Function;
@@ -14,7 +15,7 @@
* @author greg
* @since 10/19/17
*/
-public interface ServiceClient {
+public interface ServiceClient extends Closeable {
/**
* @param mediaType1 test type
* @param types list of media types
diff --git a/rd-cli-tool/src/main/java/org/rundeck/client/tool/Main.java b/rd-cli-tool/src/main/java/org/rundeck/client/tool/Main.java
index d1637fe0..2571929f 100644
--- a/rd-cli-tool/src/main/java/org/rundeck/client/tool/Main.java
+++ b/rd-cli-tool/src/main/java/org/rundeck/client/tool/Main.java
@@ -27,6 +27,7 @@
import org.rundeck.client.tool.extension.RdCommandExtension;
import org.rundeck.client.tool.util.AdaptedToolbeltOutput;
import org.rundeck.client.tool.util.ExtensionLoaderUtil;
+import org.rundeck.client.tool.util.Resources;
import org.rundeck.client.util.*;
import org.rundeck.toolbelt.*;
import org.rundeck.toolbelt.format.json.jackson.JsonFormatter;
@@ -37,6 +38,8 @@
import org.yaml.snakeyaml.nodes.Tag;
import org.yaml.snakeyaml.representer.Representer;
+import java.io.Closeable;
+import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.*;
@@ -64,18 +67,21 @@ public class Main {
RundeckClient.Builder.getUserAgent("rd-cli-tool/" + org.rundeck.client.Version.VERSION);
public static void main(String[] args) throws CommandRunFailure {
- Rd rd = new Rd(new Env());
- Tool tool = tool(rd);
boolean success = false;
- try {
- success = tool.runMain(args, false);
- } catch (RequestFailed failure) {
- rd.getOutput().error(failure.getMessage());
- if (rd.getDebugLevel() > 0) {
- StringWriter sb = new StringWriter();
- failure.printStackTrace(new PrintWriter(sb));
- rd.getOutput().error(sb.toString());
+ try (Rd rd = new Rd(new Env())) {
+ Tool tool = tool(rd);
+ try {
+ success = tool.runMain(args, false);
+ } catch (RequestFailed failure) {
+ rd.getOutput().error(failure.getMessage());
+ if (rd.getDebugLevel() > 0) {
+ StringWriter sb = new StringWriter();
+ failure.printStackTrace(new PrintWriter(sb));
+ rd.getOutput().error(sb.toString());
+ }
}
+ } catch (IOException e) {
+ e.printStackTrace();
}
if (!success) {
System.exit(2);
@@ -232,7 +238,8 @@ public static Tool tool(final Rd rd) {
return belt.buckle();
}
- static class Rd extends ExtConfigSource implements RdApp, RdClientConfig {
+ static class Rd extends ExtConfigSource implements RdApp, RdClientConfig, Closeable {
+ private final Resources resources = new Resources();
Client client;
private CommandOutput output;
@@ -264,7 +271,7 @@ public String getDateFormat() {
public Client getClient() throws InputError {
if (null == client) {
try {
- client = Main.createClient(this);
+ client = resources.add(Main.createClient(this));
} catch (ConfigSourceError configSourceError) {
throw new InputError(configSourceError.getMessage());
}
@@ -275,7 +282,7 @@ public Client getClient() throws InputError {
@Override
public Client getClient(final int version) throws InputError {
try {
- client = Main.createClient(this, version);
+ client = resources.add(Main.createClient(this, version));
} catch (ConfigSourceError configSourceError) {
throw new InputError(configSourceError.getMessage());
}
@@ -285,7 +292,7 @@ public Client getClient(final int version) throws InputError {
@Override
public ServiceClient getClient(final Class api, final int version) throws InputError {
try {
- return Main.createClient(this, api, version);
+ return resources.add(Main.createClient(this, api, version));
} catch (ConfigSourceError configSourceError) {
throw new InputError(configSourceError.getMessage());
}
@@ -294,7 +301,7 @@ public ServiceClient getClient(final Class api, final int version) thr
@Override
public ServiceClient getClient(final Class api) throws InputError {
try {
- return Main.createClient(this, api, null);
+ return resources.add(Main.createClient(this, api, null));
} catch (ConfigSourceError configSourceError) {
throw new InputError(configSourceError.getMessage());
}
@@ -328,6 +335,11 @@ public CommandOutput getOutput() {
public void setOutput(CommandOutput output) {
this.output = output;
}
+
+ @Override
+ public void close() throws IOException {
+ resources.close();
+ }
}
private static void setupColor(final ToolBelt belt, RdClientConfig config) {
diff --git a/rd-cli-tool/src/main/java/org/rundeck/client/tool/util/Resources.java b/rd-cli-tool/src/main/java/org/rundeck/client/tool/util/Resources.java
new file mode 100644
index 00000000..d8938a66
--- /dev/null
+++ b/rd-cli-tool/src/main/java/org/rundeck/client/tool/util/Resources.java
@@ -0,0 +1,34 @@
+package org.rundeck.client.tool.util;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+
+/**
+ * Holds collection of closeable resources
+ */
+public class Resources
+ implements Closeable
+{
+ private final Collection closeableResources = new ArrayList<>();
+
+ public T add(T closeable) {
+ closeableResources.add(closeable);
+ return closeable;
+ }
+
+ @Override
+ public void close() throws IOException {
+ closeableResources.forEach(
+ closeable -> {
+ try {
+ closeable.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ );
+ closeableResources.clear();
+ }
+}