Skip to content

Commit d16f1ff

Browse files
committed
[Core] Throw exception when multiple object factories are found
When multiple object factories are available on the classpath Cucumber would print out a warning and fall back to the default object factory. With the introduction of `cucumber.object-factory` the user can specify exactly which object factory should be used. There should be no need for a soft failure anymore.
1 parent 5943b20 commit d16f1ff

File tree

2 files changed

+19
-10
lines changed

2 files changed

+19
-10
lines changed

core/README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ sub modules together e.g. `cucumber-junit` and `cucumber-java`.
88

99
## Backend ##
1010

11-
Backends consists of two components an a Backend and ObjectFactory. Together
12-
they are responsible for discovering glue classes, registering step definitions
11+
Backends consists of two components, a `Backend` and `ObjectFactory`. They are
12+
respectively responsible for discovering glue classes, registering step definitions
1313
and creating instances of said glue classes.
1414

1515
## Plugin ##

core/src/main/java/io/cucumber/core/runtime/ObjectFactoryServiceLoader.java

+17-8
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
import java.util.Iterator;
1010
import java.util.Map;
1111
import java.util.ServiceLoader;
12+
import java.util.stream.Collectors;
13+
import java.util.stream.Stream;
1214

1315
import static java.util.Objects.requireNonNull;
1416

@@ -71,19 +73,26 @@ private static ObjectFactory loadSingleObjectFactoryOrDefault(ServiceLoader<Obje
7173
}
7274

7375
if (objectFactories.hasNext()) {
74-
System.out.println(getMultipleObjectFactoryLogMessage());
75-
objectFactory = new DefaultJavaObjectFactory();
76+
ObjectFactory extraObjectFactory = objectFactories.next();
77+
throw new CucumberException(getMultipleObjectFactoryLogMessage(objectFactory, extraObjectFactory));
7678
}
7779
return objectFactory;
7880
}
7981

80-
private static String getMultipleObjectFactoryLogMessage() {
82+
private static String getMultipleObjectFactoryLogMessage(ObjectFactory... objectFactories) {
83+
String factoryNames = Stream.of(objectFactories)
84+
.map(Object::getClass)
85+
.map(Class::getName)
86+
.collect(Collectors.joining(", "));
87+
8188
return "More than one Cucumber ObjectFactory was found in the classpath\n" +
8289
"\n" +
83-
"You probably may have included, for instance, cucumber-spring AND cucumber-guice as part of\n" +
84-
"your dependencies. When this happens, Cucumber falls back to instantiating the\n" +
85-
"DefaultJavaObjectFactory implementation which doesn't provide IoC.\n" +
86-
"In order to enjoy IoC features, please remove the unnecessary dependencies from your classpath.\n";
90+
"Found: " + factoryNames +"\n" +
91+
"\n" +
92+
"You may have included, for instance, cucumber-spring AND cucumber-guice as part of\n" +
93+
"your dependencies. When this happens, Cucumber can't decide which to use.\n" +
94+
"In order to enjoy dependency injection features, either remove the unnecessary dependencies" +
95+
"from your classpath or use the `cucumber.object-factory` property or `@CucumberOptions(objectFactory=...)` to select one.\n";
8796
}
8897

8998
/**
@@ -121,7 +130,7 @@ private <T> T cacheNewInstance(Class<T> type) {
121130
instances.put(type, instance);
122131
return instance;
123132
} catch (NoSuchMethodException e) {
124-
throw new CucumberException(String.format("%s doesn't have an empty constructor. If you need DI, put cucumber-picocontainer on the classpath", type), e);
133+
throw new CucumberException(String.format("%s doesn't have an empty constructor. If you need dependency injection, put cucumber-picocontainer on the classpath", type), e);
125134
} catch (Exception e) {
126135
throw new CucumberException(String.format("Failed to instantiate %s", type), e);
127136
}

0 commit comments

Comments
 (0)