From d4fcbeaf18ce43180f19934ac9a6bc207f147ea1 Mon Sep 17 00:00:00 2001 From: PJ Fanning Date: Wed, 4 Jul 2018 19:14:40 +0100 Subject: [PATCH 1/8] use thread local (optionally) for context setting --- .../main/java/io/intercom/api/Intercom.java | 73 ++++++++++++------- 1 file changed, 47 insertions(+), 26 deletions(-) diff --git a/intercom-java/src/main/java/io/intercom/api/Intercom.java b/intercom-java/src/main/java/io/intercom/api/Intercom.java index 6fb5171a..c2acd50d 100644 --- a/intercom-java/src/main/java/io/intercom/api/Intercom.java +++ b/intercom-java/src/main/java/io/intercom/api/Intercom.java @@ -4,11 +4,21 @@ public class Intercom { + static class Context { + private volatile AuthKeyType authKeyType = AuthKeyType.API_KEY; + private volatile String apiKey; + private volatile String token; + private volatile String appID; + private volatile int connectionTimeout = 3 * 1000; + private volatile int requestTimeout = 60 * 1000; + private volatile boolean requestUsingCaches = false; + } + private static final URI API_BASE_URI = URI.create("https://api.intercom.io/"); - private static volatile URI apiBaseURI = API_BASE_URI; + private static volatile boolean useThreadLocal = false; - private static volatile AuthKeyType authKeyType = AuthKeyType.API_KEY; + private static volatile URI apiBaseURI = API_BASE_URI; enum AuthKeyType { API_KEY, @@ -19,17 +29,20 @@ enum AuthKeyType { public static final String USER_AGENT = "intercom-java/" + Intercom.VERSION; - private static volatile String apiKey; - - private static volatile String token; + private static final ThreadLocal threadContext = new ThreadLocal() { + @Override protected Context initialValue() { + return new Context(); + } + }; - private static volatile String appID; + private static final Context staticContext = new Context(); - private static volatile int connectionTimeout = 3 * 1000; - - private static volatile int requestTimeout = 60 * 1000; - - private static volatile boolean requestUsingCaches = false; + private static Context getContext() { + if (useThreadLocal) { + return threadContext.get(); + } + return staticContext; + } private static volatile HttpConnectorSupplier httpConnectorSupplier = HttpConnectorSupplier.defaultSupplier; @@ -38,29 +51,29 @@ public static long currentTimestamp() { } public static int getConnectionTimeout() { - return connectionTimeout; + return getContext().connectionTimeout; } @SuppressWarnings("UnusedDeclaration") public static void setConnectionTimeout(int connectionTimeout) { - Intercom.connectionTimeout = connectionTimeout; + getContext().connectionTimeout = connectionTimeout; } public static int getRequestTimeout() { - return requestTimeout; + return getContext().requestTimeout; } @SuppressWarnings("UnusedDeclaration") public static void setRequestTimeout(int requestTimeout) { - Intercom.requestTimeout = requestTimeout; + getContext().requestTimeout = requestTimeout; } public static boolean isRequestUsingCaches() { - return requestUsingCaches; + return getContext().requestUsingCaches; } public static void setRequestUsingCaches(boolean requestUsingCaches) { - Intercom.requestUsingCaches = requestUsingCaches; + getContext().requestUsingCaches = requestUsingCaches; } public static HttpConnectorSupplier getHttpConnectorSupplier() { @@ -72,25 +85,27 @@ public static void setHttpConnectorSupplier(HttpConnectorSupplier supplier) { } public static String getAppID() { - return appID; + return getContext().appID; } public static void setAppID(String appID) { - Intercom.appID = appID; + getContext().appID = appID; } public static void setToken(String token) { - authKeyType = AuthKeyType.TOKEN; - Intercom.token = token; + Context context = getContext(); + context.authKeyType = AuthKeyType.TOKEN; + context.token = token; } public static String getApiKey() { - return Intercom.apiKey; + return getContext().apiKey; } public static void setApiKey(String apiKey) { - authKeyType = AuthKeyType.API_KEY; - Intercom.apiKey = apiKey; + Context context = getContext(); + context.authKeyType = AuthKeyType.API_KEY; + context.apiKey = apiKey; } public static URI getApiBaseURI() { @@ -102,12 +117,18 @@ public static void setApiBaseURI(URI apiBaseURI) { } static AuthKeyType getAuthKeyType() { - return authKeyType; + return getContext().authKeyType; } public static String getToken() { - return token; + return getContext().token; } + public static boolean usesThreadLocal() { + return Intercom.useThreadLocal; + } + public static void setUseThreadLocal(boolean useThreadLocal) { + Intercom.useThreadLocal = useThreadLocal; + } } From d22111ec32fe2e271c647e1fbbff3d5378b62445 Mon Sep 17 00:00:00 2001 From: PJ Fanning Date: Wed, 11 Jul 2018 18:38:38 +0100 Subject: [PATCH 2/8] add threaded tests for intercom configs --- .../main/java/io/intercom/api/Intercom.java | 2 + .../java/io/intercom/api/IntercomTest.java | 173 ++++++++++++++++++ 2 files changed, 175 insertions(+) create mode 100644 intercom-java/src/test/java/io/intercom/api/IntercomTest.java diff --git a/intercom-java/src/main/java/io/intercom/api/Intercom.java b/intercom-java/src/main/java/io/intercom/api/Intercom.java index c2acd50d..d9525665 100644 --- a/intercom-java/src/main/java/io/intercom/api/Intercom.java +++ b/intercom-java/src/main/java/io/intercom/api/Intercom.java @@ -96,6 +96,7 @@ public static void setToken(String token) { Context context = getContext(); context.authKeyType = AuthKeyType.TOKEN; context.token = token; + context.apiKey = null; } public static String getApiKey() { @@ -106,6 +107,7 @@ public static void setApiKey(String apiKey) { Context context = getContext(); context.authKeyType = AuthKeyType.API_KEY; context.apiKey = apiKey; + context.token = null; } public static URI getApiBaseURI() { diff --git a/intercom-java/src/test/java/io/intercom/api/IntercomTest.java b/intercom-java/src/test/java/io/intercom/api/IntercomTest.java new file mode 100644 index 00000000..39c9f2d8 --- /dev/null +++ b/intercom-java/src/test/java/io/intercom/api/IntercomTest.java @@ -0,0 +1,173 @@ +package io.intercom.api; + +import org.junit.After; +import org.junit.Test; + +import java.util.Random; + +import static org.junit.Assert.*; + +public class IntercomTest { + + @After + public void tearDown() { + Intercom.setUseThreadLocal(false); + } + + @Test + public void testUseThreadLocal() { + Intercom.setUseThreadLocal(false); + assertFalse(Intercom.usesThreadLocal()); + Intercom.setUseThreadLocal(true); + assertTrue(Intercom.usesThreadLocal()); + } + + @Test + public void testApiKey() { + Intercom.setApiKey("k1"); + assertEquals("k1", Intercom.getApiKey()); + assertEquals(Intercom.AuthKeyType.API_KEY, Intercom.getAuthKeyType()); + assertNull(Intercom.getToken()); + } + + @Test + public void testToken() { + Intercom.setToken("t1"); + assertEquals("t1", Intercom.getToken()); + assertEquals(Intercom.AuthKeyType.TOKEN, Intercom.getAuthKeyType()); + assertNull(Intercom.getApiKey()); + } + + @Test + public void testStaticContext() throws Exception { + Intercom.setApiKey("k1"); + assertEquals("k1", Intercom.getApiKey()); + assertNull(Intercom.getToken()); + assertEquals(Intercom.AuthKeyType.API_KEY, Intercom.getAuthKeyType()); + Intercom.setAppID("app1"); + assertEquals("app1", Intercom.getAppID()); + Intercom.setConnectionTimeout(98765); + assertEquals(98765, Intercom.getConnectionTimeout()); + Intercom.setRequestTimeout(12345); + assertEquals(12345, Intercom.getRequestTimeout()); + Intercom.setRequestUsingCaches(true); + assertTrue(Intercom.isRequestUsingCaches()); + + ThreadTester tt1 = new ThreadTester(); + ThreadTester tt2 = new ThreadTester(); + new Thread(tt1).run(); + new Thread(tt2).run(); + tt1.waitUntilComplete(); + tt2.waitUntilComplete(); + + assertEquals(Intercom.getApiKey(), tt1.apiKey); + assertEquals(Intercom.getAuthKeyType(), tt1.authKeyType); + assertEquals(Intercom.getToken(), tt1.token); + assertEquals(Intercom.getConnectionTimeout(), tt1.connectionTimeout); + assertEquals(Intercom.getRequestTimeout(), tt1.requestTimeout); + assertEquals(Intercom.isRequestUsingCaches(), tt1.requestUsingCaches); + + assertEquals(Intercom.getApiKey(), tt2.apiKey); + assertEquals(Intercom.getAuthKeyType(), tt2.authKeyType); + assertEquals(Intercom.getToken(), tt2.token); + assertEquals(Intercom.getConnectionTimeout(), tt2.connectionTimeout); + assertEquals(Intercom.getRequestTimeout(), tt2.requestTimeout); + assertEquals(Intercom.isRequestUsingCaches(), tt2.requestUsingCaches); + } + + @Test + public void testThreadLocalContext() throws Exception { + Intercom.setUseThreadLocal(true); + + ThreadLocalTester1 tt1 = new ThreadLocalTester1(); + ThreadLocalTester2 tt2 = new ThreadLocalTester2(); + new Thread(tt1).run(); + new Thread(tt2).run(); + tt1.waitUntilComplete(); + tt2.waitUntilComplete(); + + assertEquals(tt1.localToken, tt1.token); + assertNull(tt1.apiKey); + assertEquals(Intercom.AuthKeyType.TOKEN, tt1.authKeyType); + assertEquals(tt1.localConnectionTimeout, tt1.connectionTimeout); + assertEquals(tt1.localRequestTimeout, tt1.requestTimeout); + assertEquals(tt1.localRequestUsingCaches, tt1.requestUsingCaches); + + assertEquals(tt2.localApiKey, tt2.apiKey); + assertNull(tt2.token); + assertEquals(Intercom.AuthKeyType.API_KEY, tt2.authKeyType); + assertEquals(tt2.localConnectionTimeout, tt2.connectionTimeout); + assertEquals(tt2.localRequestTimeout, tt2.requestTimeout); + assertEquals(tt2.localRequestUsingCaches, tt2.requestUsingCaches); + } + + class ThreadTester implements Runnable { + String apiKey, appId, token; + Intercom.AuthKeyType authKeyType; + int connectionTimeout = -1; + int requestTimeout = -1; + Boolean requestUsingCaches; + boolean completed = false; + + @Override + public void run() { + apiKey = Intercom.getApiKey(); + authKeyType = Intercom.getAuthKeyType(); + token = Intercom.getToken(); + appId = Intercom.getAppID(); + connectionTimeout = Intercom.getConnectionTimeout(); + requestTimeout = Intercom.getRequestTimeout(); + requestUsingCaches = Intercom.isRequestUsingCaches(); + completed = true; + synchronized (this) { + notify(); + } + } + + void waitUntilComplete() throws InterruptedException { + synchronized (this) { + while(!completed) { + wait(5000); + } + } + } + } + + class ThreadLocalTester1 extends ThreadTester { + final Random rnd = new Random(); + final String localToken = "tx"; + final String localAppId = "appx"; + final int localConnectionTimeout = rnd.nextInt(); + final int localRequestTimeout = rnd.nextInt(); + final boolean localRequestUsingCaches = rnd.nextBoolean(); + + @Override + public void run() { + Intercom.setToken(localToken); + Intercom.setAppID(localAppId); + Intercom.setConnectionTimeout(localConnectionTimeout); + Intercom.setRequestTimeout(localRequestTimeout); + Intercom.setRequestUsingCaches(localRequestUsingCaches); + super.run(); + } + } + + class ThreadLocalTester2 extends ThreadTester { + final Random rnd = new Random(); + final String localApiKey = "api"; + final String localAppId = "appId"; + final int localConnectionTimeout = rnd.nextInt(); + final int localRequestTimeout = rnd.nextInt(); + final boolean localRequestUsingCaches = rnd.nextBoolean(); + + @Override + public void run() { + Intercom.setApiKey(localApiKey); + Intercom.setAppID(localAppId); + Intercom.setConnectionTimeout(localConnectionTimeout); + Intercom.setRequestTimeout(localRequestTimeout); + Intercom.setRequestUsingCaches(localRequestUsingCaches); + super.run(); + } + } +} \ No newline at end of file From 9e5d754f1f1c52f8b17f64701f01874718254fa1 Mon Sep 17 00:00:00 2001 From: PJ Fanning Date: Wed, 11 Jul 2018 19:57:09 +0100 Subject: [PATCH 3/8] extend test --- .../src/test/java/io/intercom/api/IntercomTest.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/intercom-java/src/test/java/io/intercom/api/IntercomTest.java b/intercom-java/src/test/java/io/intercom/api/IntercomTest.java index 39c9f2d8..fbb556fa 100644 --- a/intercom-java/src/test/java/io/intercom/api/IntercomTest.java +++ b/intercom-java/src/test/java/io/intercom/api/IntercomTest.java @@ -17,9 +17,15 @@ public void tearDown() { @Test public void testUseThreadLocal() { Intercom.setUseThreadLocal(false); + Intercom.setToken("tx"); assertFalse(Intercom.usesThreadLocal()); + assertEquals("tx", Intercom.getToken()); Intercom.setUseThreadLocal(true); assertTrue(Intercom.usesThreadLocal()); + assertNotEquals("tx", Intercom.getToken()); + Intercom.setUseThreadLocal(false); + assertFalse(Intercom.usesThreadLocal()); + assertEquals("tx", Intercom.getToken()); } @Test From 2241d04118e696a64bcbbe9ff51b38d07cafb861 Mon Sep 17 00:00:00 2001 From: PJ Fanning Date: Wed, 4 Jul 2018 19:14:40 +0100 Subject: [PATCH 4/8] use thread local (optionally) for context setting --- .../main/java/io/intercom/api/Intercom.java | 73 ++++++++++++------- 1 file changed, 47 insertions(+), 26 deletions(-) diff --git a/intercom-java/src/main/java/io/intercom/api/Intercom.java b/intercom-java/src/main/java/io/intercom/api/Intercom.java index 6fb5171a..c2acd50d 100644 --- a/intercom-java/src/main/java/io/intercom/api/Intercom.java +++ b/intercom-java/src/main/java/io/intercom/api/Intercom.java @@ -4,11 +4,21 @@ public class Intercom { + static class Context { + private volatile AuthKeyType authKeyType = AuthKeyType.API_KEY; + private volatile String apiKey; + private volatile String token; + private volatile String appID; + private volatile int connectionTimeout = 3 * 1000; + private volatile int requestTimeout = 60 * 1000; + private volatile boolean requestUsingCaches = false; + } + private static final URI API_BASE_URI = URI.create("https://api.intercom.io/"); - private static volatile URI apiBaseURI = API_BASE_URI; + private static volatile boolean useThreadLocal = false; - private static volatile AuthKeyType authKeyType = AuthKeyType.API_KEY; + private static volatile URI apiBaseURI = API_BASE_URI; enum AuthKeyType { API_KEY, @@ -19,17 +29,20 @@ enum AuthKeyType { public static final String USER_AGENT = "intercom-java/" + Intercom.VERSION; - private static volatile String apiKey; - - private static volatile String token; + private static final ThreadLocal threadContext = new ThreadLocal() { + @Override protected Context initialValue() { + return new Context(); + } + }; - private static volatile String appID; + private static final Context staticContext = new Context(); - private static volatile int connectionTimeout = 3 * 1000; - - private static volatile int requestTimeout = 60 * 1000; - - private static volatile boolean requestUsingCaches = false; + private static Context getContext() { + if (useThreadLocal) { + return threadContext.get(); + } + return staticContext; + } private static volatile HttpConnectorSupplier httpConnectorSupplier = HttpConnectorSupplier.defaultSupplier; @@ -38,29 +51,29 @@ public static long currentTimestamp() { } public static int getConnectionTimeout() { - return connectionTimeout; + return getContext().connectionTimeout; } @SuppressWarnings("UnusedDeclaration") public static void setConnectionTimeout(int connectionTimeout) { - Intercom.connectionTimeout = connectionTimeout; + getContext().connectionTimeout = connectionTimeout; } public static int getRequestTimeout() { - return requestTimeout; + return getContext().requestTimeout; } @SuppressWarnings("UnusedDeclaration") public static void setRequestTimeout(int requestTimeout) { - Intercom.requestTimeout = requestTimeout; + getContext().requestTimeout = requestTimeout; } public static boolean isRequestUsingCaches() { - return requestUsingCaches; + return getContext().requestUsingCaches; } public static void setRequestUsingCaches(boolean requestUsingCaches) { - Intercom.requestUsingCaches = requestUsingCaches; + getContext().requestUsingCaches = requestUsingCaches; } public static HttpConnectorSupplier getHttpConnectorSupplier() { @@ -72,25 +85,27 @@ public static void setHttpConnectorSupplier(HttpConnectorSupplier supplier) { } public static String getAppID() { - return appID; + return getContext().appID; } public static void setAppID(String appID) { - Intercom.appID = appID; + getContext().appID = appID; } public static void setToken(String token) { - authKeyType = AuthKeyType.TOKEN; - Intercom.token = token; + Context context = getContext(); + context.authKeyType = AuthKeyType.TOKEN; + context.token = token; } public static String getApiKey() { - return Intercom.apiKey; + return getContext().apiKey; } public static void setApiKey(String apiKey) { - authKeyType = AuthKeyType.API_KEY; - Intercom.apiKey = apiKey; + Context context = getContext(); + context.authKeyType = AuthKeyType.API_KEY; + context.apiKey = apiKey; } public static URI getApiBaseURI() { @@ -102,12 +117,18 @@ public static void setApiBaseURI(URI apiBaseURI) { } static AuthKeyType getAuthKeyType() { - return authKeyType; + return getContext().authKeyType; } public static String getToken() { - return token; + return getContext().token; } + public static boolean usesThreadLocal() { + return Intercom.useThreadLocal; + } + public static void setUseThreadLocal(boolean useThreadLocal) { + Intercom.useThreadLocal = useThreadLocal; + } } From 676d1bc55343d214f3bb989f289b4d5a787d21e8 Mon Sep 17 00:00:00 2001 From: PJ Fanning Date: Wed, 11 Jul 2018 18:38:38 +0100 Subject: [PATCH 5/8] add threaded tests for intercom configs --- .../main/java/io/intercom/api/Intercom.java | 2 + .../java/io/intercom/api/IntercomTest.java | 173 ++++++++++++++++++ 2 files changed, 175 insertions(+) create mode 100644 intercom-java/src/test/java/io/intercom/api/IntercomTest.java diff --git a/intercom-java/src/main/java/io/intercom/api/Intercom.java b/intercom-java/src/main/java/io/intercom/api/Intercom.java index c2acd50d..d9525665 100644 --- a/intercom-java/src/main/java/io/intercom/api/Intercom.java +++ b/intercom-java/src/main/java/io/intercom/api/Intercom.java @@ -96,6 +96,7 @@ public static void setToken(String token) { Context context = getContext(); context.authKeyType = AuthKeyType.TOKEN; context.token = token; + context.apiKey = null; } public static String getApiKey() { @@ -106,6 +107,7 @@ public static void setApiKey(String apiKey) { Context context = getContext(); context.authKeyType = AuthKeyType.API_KEY; context.apiKey = apiKey; + context.token = null; } public static URI getApiBaseURI() { diff --git a/intercom-java/src/test/java/io/intercom/api/IntercomTest.java b/intercom-java/src/test/java/io/intercom/api/IntercomTest.java new file mode 100644 index 00000000..39c9f2d8 --- /dev/null +++ b/intercom-java/src/test/java/io/intercom/api/IntercomTest.java @@ -0,0 +1,173 @@ +package io.intercom.api; + +import org.junit.After; +import org.junit.Test; + +import java.util.Random; + +import static org.junit.Assert.*; + +public class IntercomTest { + + @After + public void tearDown() { + Intercom.setUseThreadLocal(false); + } + + @Test + public void testUseThreadLocal() { + Intercom.setUseThreadLocal(false); + assertFalse(Intercom.usesThreadLocal()); + Intercom.setUseThreadLocal(true); + assertTrue(Intercom.usesThreadLocal()); + } + + @Test + public void testApiKey() { + Intercom.setApiKey("k1"); + assertEquals("k1", Intercom.getApiKey()); + assertEquals(Intercom.AuthKeyType.API_KEY, Intercom.getAuthKeyType()); + assertNull(Intercom.getToken()); + } + + @Test + public void testToken() { + Intercom.setToken("t1"); + assertEquals("t1", Intercom.getToken()); + assertEquals(Intercom.AuthKeyType.TOKEN, Intercom.getAuthKeyType()); + assertNull(Intercom.getApiKey()); + } + + @Test + public void testStaticContext() throws Exception { + Intercom.setApiKey("k1"); + assertEquals("k1", Intercom.getApiKey()); + assertNull(Intercom.getToken()); + assertEquals(Intercom.AuthKeyType.API_KEY, Intercom.getAuthKeyType()); + Intercom.setAppID("app1"); + assertEquals("app1", Intercom.getAppID()); + Intercom.setConnectionTimeout(98765); + assertEquals(98765, Intercom.getConnectionTimeout()); + Intercom.setRequestTimeout(12345); + assertEquals(12345, Intercom.getRequestTimeout()); + Intercom.setRequestUsingCaches(true); + assertTrue(Intercom.isRequestUsingCaches()); + + ThreadTester tt1 = new ThreadTester(); + ThreadTester tt2 = new ThreadTester(); + new Thread(tt1).run(); + new Thread(tt2).run(); + tt1.waitUntilComplete(); + tt2.waitUntilComplete(); + + assertEquals(Intercom.getApiKey(), tt1.apiKey); + assertEquals(Intercom.getAuthKeyType(), tt1.authKeyType); + assertEquals(Intercom.getToken(), tt1.token); + assertEquals(Intercom.getConnectionTimeout(), tt1.connectionTimeout); + assertEquals(Intercom.getRequestTimeout(), tt1.requestTimeout); + assertEquals(Intercom.isRequestUsingCaches(), tt1.requestUsingCaches); + + assertEquals(Intercom.getApiKey(), tt2.apiKey); + assertEquals(Intercom.getAuthKeyType(), tt2.authKeyType); + assertEquals(Intercom.getToken(), tt2.token); + assertEquals(Intercom.getConnectionTimeout(), tt2.connectionTimeout); + assertEquals(Intercom.getRequestTimeout(), tt2.requestTimeout); + assertEquals(Intercom.isRequestUsingCaches(), tt2.requestUsingCaches); + } + + @Test + public void testThreadLocalContext() throws Exception { + Intercom.setUseThreadLocal(true); + + ThreadLocalTester1 tt1 = new ThreadLocalTester1(); + ThreadLocalTester2 tt2 = new ThreadLocalTester2(); + new Thread(tt1).run(); + new Thread(tt2).run(); + tt1.waitUntilComplete(); + tt2.waitUntilComplete(); + + assertEquals(tt1.localToken, tt1.token); + assertNull(tt1.apiKey); + assertEquals(Intercom.AuthKeyType.TOKEN, tt1.authKeyType); + assertEquals(tt1.localConnectionTimeout, tt1.connectionTimeout); + assertEquals(tt1.localRequestTimeout, tt1.requestTimeout); + assertEquals(tt1.localRequestUsingCaches, tt1.requestUsingCaches); + + assertEquals(tt2.localApiKey, tt2.apiKey); + assertNull(tt2.token); + assertEquals(Intercom.AuthKeyType.API_KEY, tt2.authKeyType); + assertEquals(tt2.localConnectionTimeout, tt2.connectionTimeout); + assertEquals(tt2.localRequestTimeout, tt2.requestTimeout); + assertEquals(tt2.localRequestUsingCaches, tt2.requestUsingCaches); + } + + class ThreadTester implements Runnable { + String apiKey, appId, token; + Intercom.AuthKeyType authKeyType; + int connectionTimeout = -1; + int requestTimeout = -1; + Boolean requestUsingCaches; + boolean completed = false; + + @Override + public void run() { + apiKey = Intercom.getApiKey(); + authKeyType = Intercom.getAuthKeyType(); + token = Intercom.getToken(); + appId = Intercom.getAppID(); + connectionTimeout = Intercom.getConnectionTimeout(); + requestTimeout = Intercom.getRequestTimeout(); + requestUsingCaches = Intercom.isRequestUsingCaches(); + completed = true; + synchronized (this) { + notify(); + } + } + + void waitUntilComplete() throws InterruptedException { + synchronized (this) { + while(!completed) { + wait(5000); + } + } + } + } + + class ThreadLocalTester1 extends ThreadTester { + final Random rnd = new Random(); + final String localToken = "tx"; + final String localAppId = "appx"; + final int localConnectionTimeout = rnd.nextInt(); + final int localRequestTimeout = rnd.nextInt(); + final boolean localRequestUsingCaches = rnd.nextBoolean(); + + @Override + public void run() { + Intercom.setToken(localToken); + Intercom.setAppID(localAppId); + Intercom.setConnectionTimeout(localConnectionTimeout); + Intercom.setRequestTimeout(localRequestTimeout); + Intercom.setRequestUsingCaches(localRequestUsingCaches); + super.run(); + } + } + + class ThreadLocalTester2 extends ThreadTester { + final Random rnd = new Random(); + final String localApiKey = "api"; + final String localAppId = "appId"; + final int localConnectionTimeout = rnd.nextInt(); + final int localRequestTimeout = rnd.nextInt(); + final boolean localRequestUsingCaches = rnd.nextBoolean(); + + @Override + public void run() { + Intercom.setApiKey(localApiKey); + Intercom.setAppID(localAppId); + Intercom.setConnectionTimeout(localConnectionTimeout); + Intercom.setRequestTimeout(localRequestTimeout); + Intercom.setRequestUsingCaches(localRequestUsingCaches); + super.run(); + } + } +} \ No newline at end of file From 48930ceadb8832bb97cbaadc343dbc38d1cef072 Mon Sep 17 00:00:00 2001 From: PJ Fanning Date: Wed, 11 Jul 2018 19:57:09 +0100 Subject: [PATCH 6/8] extend test --- .../src/test/java/io/intercom/api/IntercomTest.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/intercom-java/src/test/java/io/intercom/api/IntercomTest.java b/intercom-java/src/test/java/io/intercom/api/IntercomTest.java index 39c9f2d8..fbb556fa 100644 --- a/intercom-java/src/test/java/io/intercom/api/IntercomTest.java +++ b/intercom-java/src/test/java/io/intercom/api/IntercomTest.java @@ -17,9 +17,15 @@ public void tearDown() { @Test public void testUseThreadLocal() { Intercom.setUseThreadLocal(false); + Intercom.setToken("tx"); assertFalse(Intercom.usesThreadLocal()); + assertEquals("tx", Intercom.getToken()); Intercom.setUseThreadLocal(true); assertTrue(Intercom.usesThreadLocal()); + assertNotEquals("tx", Intercom.getToken()); + Intercom.setUseThreadLocal(false); + assertFalse(Intercom.usesThreadLocal()); + assertEquals("tx", Intercom.getToken()); } @Test From cd9ce336482d4715397bf7744602e2ec3afb0f40 Mon Sep 17 00:00:00 2001 From: PJ Fanning Date: Mon, 10 Sep 2018 19:00:02 +0100 Subject: [PATCH 7/8] Add clearThreadLocalContexts method --- .../main/java/io/intercom/api/Intercom.java | 18 +++++++++++++----- .../java/io/intercom/api/IntercomTest.java | 11 +++++++++++ 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/intercom-java/src/main/java/io/intercom/api/Intercom.java b/intercom-java/src/main/java/io/intercom/api/Intercom.java index b3890417..a1f4b332 100644 --- a/intercom-java/src/main/java/io/intercom/api/Intercom.java +++ b/intercom-java/src/main/java/io/intercom/api/Intercom.java @@ -29,11 +29,7 @@ enum AuthKeyType { public static final String USER_AGENT = "intercom-java/" + Intercom.VERSION; - private static final ThreadLocal threadContext = new ThreadLocal() { - @Override protected Context initialValue() { - return new Context(); - } - }; + private static ThreadLocal threadContext = newThreadLocalContext(); private static final Context staticContext = new Context(); @@ -133,4 +129,16 @@ public static boolean usesThreadLocal() { public static void setUseThreadLocal(boolean useThreadLocal) { Intercom.useThreadLocal = useThreadLocal; } + + public static void clearThreadLocalContexts() { + threadContext = newThreadLocalContext(); + } + + private static ThreadLocal newThreadLocalContext() { + return new ThreadLocal() { + @Override protected Context initialValue() { + return new Context(); + } + }; + } } diff --git a/intercom-java/src/test/java/io/intercom/api/IntercomTest.java b/intercom-java/src/test/java/io/intercom/api/IntercomTest.java index fbb556fa..b6129d6c 100644 --- a/intercom-java/src/test/java/io/intercom/api/IntercomTest.java +++ b/intercom-java/src/test/java/io/intercom/api/IntercomTest.java @@ -107,6 +107,17 @@ public void testThreadLocalContext() throws Exception { assertEquals(tt2.localRequestUsingCaches, tt2.requestUsingCaches); } + @Test + public void testClearThreadLocalContexts() throws Exception { + Intercom.setUseThreadLocal(true); + + Intercom.setApiKey("testKey"); + assertEquals("testKey", Intercom.getApiKey()); + + Intercom.clearThreadLocalContexts(); + assertNull(Intercom.getApiKey()); + } + class ThreadTester implements Runnable { String apiKey, appId, token; Intercom.AuthKeyType authKeyType; From 46193bdf8854276d83c9b5222c504bf069279732 Mon Sep 17 00:00:00 2001 From: PJ Fanning Date: Tue, 11 Sep 2018 11:26:37 +0100 Subject: [PATCH 8/8] add clearThreadLocalContext() --- .../main/java/io/intercom/api/Intercom.java | 4 ++++ .../java/io/intercom/api/IntercomTest.java | 19 +++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/intercom-java/src/main/java/io/intercom/api/Intercom.java b/intercom-java/src/main/java/io/intercom/api/Intercom.java index a1f4b332..9bc5e71d 100644 --- a/intercom-java/src/main/java/io/intercom/api/Intercom.java +++ b/intercom-java/src/main/java/io/intercom/api/Intercom.java @@ -130,6 +130,10 @@ public static void setUseThreadLocal(boolean useThreadLocal) { Intercom.useThreadLocal = useThreadLocal; } + public static void clearThreadLocalContext() { + threadContext.remove(); + } + public static void clearThreadLocalContexts() { threadContext = newThreadLocalContext(); } diff --git a/intercom-java/src/test/java/io/intercom/api/IntercomTest.java b/intercom-java/src/test/java/io/intercom/api/IntercomTest.java index b6129d6c..6c73f256 100644 --- a/intercom-java/src/test/java/io/intercom/api/IntercomTest.java +++ b/intercom-java/src/test/java/io/intercom/api/IntercomTest.java @@ -116,6 +116,23 @@ public void testClearThreadLocalContexts() throws Exception { Intercom.clearThreadLocalContexts(); assertNull(Intercom.getApiKey()); + + Intercom.setApiKey("testKey2"); + assertEquals("testKey2", Intercom.getApiKey()); + } + + @Test + public void testClearThreadLocalContext() throws Exception { + Intercom.setUseThreadLocal(true); + + Intercom.setApiKey("testKey"); + assertEquals("testKey", Intercom.getApiKey()); + + Intercom.clearThreadLocalContext(); + assertNull(Intercom.getApiKey()); + + Intercom.setApiKey("testKey2"); + assertEquals("testKey2", Intercom.getApiKey()); } class ThreadTester implements Runnable { @@ -160,6 +177,7 @@ class ThreadLocalTester1 extends ThreadTester { @Override public void run() { + Intercom.clearThreadLocalContext(); Intercom.setToken(localToken); Intercom.setAppID(localAppId); Intercom.setConnectionTimeout(localConnectionTimeout); @@ -179,6 +197,7 @@ class ThreadLocalTester2 extends ThreadTester { @Override public void run() { + Intercom.clearThreadLocalContext(); Intercom.setApiKey(localApiKey); Intercom.setAppID(localAppId); Intercom.setConnectionTimeout(localConnectionTimeout);