Skip to content

Commit b37395b

Browse files
author
Mykola Mokhnach
authored
Improve the error message on session creation (#994)
* Improve the error message on session creation * Use single quotes * Better error message for InvocationTargetException exception * fix checkstyle
1 parent 6d408e8 commit b37395b

File tree

6 files changed

+133
-14
lines changed

6 files changed

+133
-14
lines changed

build.gradle

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ apply plugin: 'checkstyle'
77
apply plugin: 'signing'
88
apply plugin: 'maven-publish'
99

10+
import org.apache.tools.ant.filters.*
11+
1012
group 'io.appium'
1113
version '6.1.0'
1214

@@ -50,21 +52,19 @@ compileJava {
5052
]
5153
}
5254

53-
ext.seleniumVersion = '3.14.0'
54-
5555
dependencies {
56-
compile ("org.seleniumhq.selenium:selenium-java:${seleniumVersion}") {
56+
compile ("org.seleniumhq.selenium:selenium-java:${project.property('selenium.version')}") {
5757
force = true
5858

5959
exclude group: 'com.google.code.gson'
6060
exclude module: 'htmlunit-driver'
6161
exclude group: 'net.sourceforge.htmlunit'
6262

6363
}
64-
compile ("org.seleniumhq.selenium:selenium-support:${seleniumVersion}") {
64+
compile ("org.seleniumhq.selenium:selenium-support:${project.property('selenium.version')}") {
6565
force = true
6666
}
67-
compile ("org.seleniumhq.selenium:selenium-api:${seleniumVersion}") {
67+
compile ("org.seleniumhq.selenium:selenium-api:${project.property('selenium.version')}") {
6868
force = true
6969
}
7070
compile 'com.google.code.gson:gson:2.8.4'
@@ -199,6 +199,12 @@ wrapper {
199199
distributionType = Wrapper.DistributionType.ALL
200200
}
201201

202+
processResources {
203+
filter ReplaceTokens, tokens: [
204+
'selenium.version': project.property('selenium.version')
205+
]
206+
}
207+
202208
task xcuiTest( type: Test ) {
203209
useJUnit()
204210
testLogging.showStandardStreams = true

gradle.properties

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,5 @@ signing.secretKeyRingFile=PathToYourKeyRingFile
66

77
ossrhUsername=your-jira-id
88
ossrhPassword=your-jira-password
9+
10+
selenium.version=3.14.0
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
package io.appium.java_client.internal;
2+
3+
import java.io.IOException;
4+
import java.io.InputStream;
5+
import java.io.UncheckedIOException;
6+
import java.util.Map;
7+
import java.util.Optional;
8+
import java.util.Properties;
9+
import java.util.concurrent.ConcurrentHashMap;
10+
11+
public class Config {
12+
private static Config mainInstance = null;
13+
private static final String MAIN_CONFIG = "main.properties";
14+
private static final Map<String, Properties> cache = new ConcurrentHashMap<>();
15+
private final String configName;
16+
17+
/**
18+
* Retrieve a facade for the main config.
19+
*
20+
* @return interaction helper for 'main.properties' config
21+
*/
22+
public static synchronized Config main() {
23+
if (mainInstance == null) {
24+
mainInstance = new Config(MAIN_CONFIG);
25+
}
26+
return mainInstance;
27+
}
28+
29+
private Config(String configName) {
30+
this.configName = configName;
31+
}
32+
33+
/**
34+
* Retrieve a value from properties file.
35+
*
36+
* @param key the name of the corresponding key which value to retrieve
37+
* @param valueType the expected type of the value to be retrieved
38+
* @return the actual value
39+
* @throws IllegalArgumentException if the given key does not exist
40+
* @throws ClassCastException if the retrieved value cannot be cast to `valueType` type
41+
*/
42+
public <T> T getValue(String key, Class<T> valueType) {
43+
return getOptionalValue(key, valueType)
44+
.orElseThrow(() -> new IllegalArgumentException(
45+
String.format("There is no '%s' key in '%s' config", key, configName)
46+
));
47+
}
48+
49+
/**
50+
* Retrieve a value from properties file.
51+
*
52+
* @param key the name of the corresponding key which value to retrieve
53+
* @param valueType the expected type of the value to be retrieved
54+
* @return the actual value or {@link Optional#empty()} if the key is not present
55+
* @throws UncheckedIOException if the given properties file does not exist/not accessible
56+
* @throws ClassCastException if the retrieved value cannot be cast to `valueType` type
57+
*/
58+
public <T> Optional<T> getOptionalValue(String key, Class<T> valueType) {
59+
final Properties cachedProps = cache.computeIfAbsent(configName, (k) -> {
60+
try (InputStream configFileStream = getClass().getClassLoader().getResourceAsStream(configName)) {
61+
final Properties p = new Properties();
62+
p.load(configFileStream);
63+
return p;
64+
} catch (IOException e) {
65+
throw new UncheckedIOException(String.format("Configuration file '%s' cannot be loaded",
66+
configName), e);
67+
}
68+
});
69+
return cachedProps.containsKey(key) ? Optional.of(valueType.cast(cachedProps.get(key))) : Optional.empty();
70+
}
71+
}

src/main/java/io/appium/java_client/remote/AppiumCommandExecutor.java

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import com.google.common.io.CountingOutputStream;
3131
import com.google.common.io.FileBackedOutputStream;
3232

33+
import io.appium.java_client.internal.Config;
3334
import org.openqa.selenium.Capabilities;
3435
import org.openqa.selenium.ImmutableCapabilities;
3536
import org.openqa.selenium.SessionNotCreatedException;
@@ -190,17 +191,21 @@ public Result createSession(HttpClient client, Command command)
190191
.info(format("Detected dialect: %s", toReturn.getDialect()));
191192
return toReturn;
192193
}).orElseThrow(() -> new SessionNotCreatedException(
193-
format("Unable to create new remote session. desired capabilities = %s", desired)));
194+
format("Unable to create a new remote session. Desired capabilities = %s", desired)));
194195
} catch (NoSuchMethodException | IllegalAccessException e) {
195-
throw new WebDriverException(format("It is impossible to create a new session "
196-
+ "because 'createSession' which takes %s, %s and %s was not found "
197-
+ "or it is not accessible",
198-
HttpClient.class.getSimpleName(),
199-
InputStream.class.getSimpleName(),
200-
long.class.getSimpleName()), e);
196+
throw new SessionNotCreatedException(format("Unable to create a new remote session. "
197+
+ "Make sure your project dependencies config does not override "
198+
+ "Selenium API version %s used by java-client library.",
199+
Config.main().getValue("selenium.version", String.class)), e);
201200
} catch (InvocationTargetException e) {
202-
throw new SessionNotCreatedException(
203-
format("Unable to create new remote session. Desired capabilities: %s", desired), e);
201+
String message = "Unable to create a new remote session.";
202+
if (e.getCause() != null) {
203+
if (e.getCause() instanceof WebDriverException) {
204+
message += " Please check the server log for more details.";
205+
}
206+
message += format(" Original error: %s", e.getCause().getMessage());
207+
}
208+
throw new SessionNotCreatedException(message, e);
204209
}
205210
} finally {
206211
os.reset();

src/main/resources/main.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
selenium.version[email protected]@
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package io.appium.java_client.internal;
2+
3+
import static org.hamcrest.MatcherAssert.assertThat;
4+
import static org.hamcrest.Matchers.greaterThan;
5+
import static org.junit.Assert.assertFalse;
6+
import static org.junit.Assert.assertTrue;
7+
8+
import org.junit.Test;
9+
10+
public class ConfigTest {
11+
private static final String EXISTING_KEY = "selenium.version";
12+
private static final String MISSING_KEY = "bla";
13+
14+
@Test
15+
public void verifyGettingExistingValue() {
16+
assertThat(Config.main().getValue(EXISTING_KEY, String.class).length(), greaterThan(0));
17+
assertTrue(Config.main().getOptionalValue(EXISTING_KEY, String.class).isPresent());
18+
}
19+
20+
@Test(expected = IllegalArgumentException.class)
21+
public void verifyGettingNonExistingValue() {
22+
assertThat(Config.main().getValue(MISSING_KEY, String.class).length(), greaterThan(0));
23+
}
24+
25+
@Test(expected = ClassCastException.class)
26+
public void verifyGettingExistingValueWithWrongClass() {
27+
assertThat(Config.main().getValue(EXISTING_KEY, Integer.class), greaterThan(0));
28+
}
29+
30+
@Test
31+
public void verifyGettingNonExistingOptionalValue() {
32+
assertFalse(Config.main().getOptionalValue(MISSING_KEY, String.class).isPresent());
33+
}
34+
}

0 commit comments

Comments
 (0)