Skip to content

Commit f5911e0

Browse files
committed
Merge branch 'master' into develop-v5
2 parents 84dbf34 + af05cf3 commit f5911e0

File tree

16 files changed

+470
-8
lines changed

16 files changed

+470
-8
lines changed

cdi2/README.md

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
Cucumber CDI 2
2+
==============
3+
4+
This module relies on CDI Standalone Edition (CDI SE) API to start/stop a CDI container
5+
and customize it - adding steps. It looks up the beans/steps in CDI and if not available
6+
it instantiates it as POJO with CDI injection support - unmanaged bean.
7+
8+
## Setup
9+
10+
To use it, it is important to provide your CDI SE implementation - likely Weld or Apache OpenWebBeans.
11+
12+
For Apache OpenWebBeans the dependency is:
13+
14+
```xml
15+
<dependency>
16+
<groupId>org.apache.openwebbeans</groupId>
17+
<artifactId>openwebbeans-se</artifactId>
18+
<version>2.0.10</version>
19+
<scope>test</scope>
20+
</dependency>
21+
22+
```
23+
24+
And for Weld it is:
25+
26+
```xml
27+
<dependency>
28+
<groupId>org.jboss.weld.se</groupId>
29+
<artifactId>weld-se-core</artifactId>
30+
<version>3.1.1.Final</version>
31+
<scope>test</scope>
32+
</dependency>
33+
```
34+
35+
To ensure the module is compatible with all implementations and future API version, it does not transitively bring the API.
36+
If you don't know which one to use, you can import the following one but if you develop CDI code you should already have one provided:
37+
38+
```xml
39+
<dependency>
40+
<groupId>javax.enterprise</groupId>
41+
<artifactId>cdi-api</artifactId>
42+
<version>2.0</version>
43+
</dependency>
44+
```

cdi2/pom.xml

+64
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
2+
<modelVersion>4.0.0</modelVersion>
3+
<properties>
4+
<openwebbeans.version>2.0.10</openwebbeans.version>
5+
</properties>
6+
7+
<parent>
8+
<groupId>io.cucumber</groupId>
9+
<artifactId>cucumber-jvm</artifactId>
10+
<version>4.4.0-SNAPSHOT</version>
11+
</parent>
12+
13+
<artifactId>cucumber-cdi2</artifactId>
14+
<packaging>jar</packaging>
15+
<name>Cucumber-JVM: CDI 2</name>
16+
17+
<dependencies>
18+
<dependency>
19+
<groupId>io.cucumber</groupId>
20+
<artifactId>cucumber-core</artifactId>
21+
</dependency>
22+
23+
<dependency>
24+
<groupId>javax.enterprise</groupId>
25+
<artifactId>cdi-api</artifactId>
26+
<version>2.0</version>
27+
<scope>provided</scope>
28+
</dependency>
29+
<dependency> <!-- java 11 -->
30+
<groupId>javax.annotation</groupId>
31+
<artifactId>javax.annotation-api</artifactId>
32+
<version>1.3</version>
33+
<scope>provided</scope>
34+
</dependency>
35+
36+
<dependency>
37+
<groupId>org.apache.openwebbeans</groupId>
38+
<artifactId>openwebbeans-impl</artifactId>
39+
<version>${openwebbeans.version}</version>
40+
<scope>test</scope>
41+
</dependency>
42+
<dependency>
43+
<groupId>org.apache.openwebbeans</groupId>
44+
<artifactId>openwebbeans-se</artifactId>
45+
<version>${openwebbeans.version}</version>
46+
<scope>test</scope>
47+
</dependency>
48+
<dependency>
49+
<groupId>junit</groupId>
50+
<artifactId>junit</artifactId>
51+
<scope>test</scope>
52+
</dependency>
53+
<dependency>
54+
<groupId>io.cucumber</groupId>
55+
<artifactId>cucumber-java</artifactId>
56+
<scope>test</scope>
57+
</dependency>
58+
<dependency>
59+
<groupId>io.cucumber</groupId>
60+
<artifactId>cucumber-junit</artifactId>
61+
<scope>test</scope>
62+
</dependency>
63+
</dependencies>
64+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
package io.cucumber.cdi2;
2+
3+
import io.cucumber.core.backend.ObjectFactory;
4+
5+
import javax.enterprise.inject.Instance;
6+
import javax.enterprise.inject.se.SeContainer;
7+
import javax.enterprise.inject.se.SeContainerInitializer;
8+
import javax.enterprise.inject.spi.Unmanaged;
9+
import java.util.HashMap;
10+
import java.util.Map;
11+
12+
public final class Cdi2Factory implements ObjectFactory {
13+
14+
private SeContainerInitializer initializer;
15+
private SeContainer container;
16+
private final Map<Class<?>, Unmanaged.UnmanagedInstance<?>> standaloneInstances = new HashMap<>();
17+
18+
@Override
19+
public void start() {
20+
container = getInitializer().initialize();
21+
}
22+
23+
@Override
24+
public void stop() {
25+
if (container != null) {
26+
container.close();
27+
container = null;
28+
initializer = null;
29+
}
30+
for (final Unmanaged.UnmanagedInstance<?> unmanaged : standaloneInstances.values()) {
31+
unmanaged.preDestroy();
32+
unmanaged.dispose();
33+
}
34+
standaloneInstances.clear();
35+
}
36+
37+
@Override
38+
public boolean addClass(final Class<?> clazz) {
39+
getInitializer().addBeanClasses(clazz);
40+
return true;
41+
}
42+
43+
@Override
44+
public <T> T getInstance(final Class<T> type) {
45+
final Object instance = standaloneInstances.get(type);
46+
if (instance != null) {
47+
return type.cast(instance);
48+
}
49+
final Instance<T> selected = container.select(type);
50+
if (selected.isUnsatisfied()) {
51+
final Unmanaged.UnmanagedInstance<T> value = new Unmanaged<>(container.getBeanManager(), type).newInstance();
52+
value.produce();
53+
value.inject();
54+
value.postConstruct();
55+
standaloneInstances.put(type, value);
56+
return value.get();
57+
}
58+
return selected.get();
59+
}
60+
61+
private SeContainerInitializer getInitializer() {
62+
if (initializer == null) {
63+
initializer = SeContainerInitializer.newInstance();
64+
}
65+
return initializer;
66+
}
67+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
io.cucumber.cdi2.Cdi2Factory
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package io.cucumber.cdi2;
2+
3+
import javax.enterprise.context.ApplicationScoped;
4+
5+
@ApplicationScoped
6+
public class Belly {
7+
private int cukes;
8+
9+
public void setCukes(int cukes) {
10+
this.cukes = cukes;
11+
}
12+
13+
public int getCukes() {
14+
return cukes;
15+
}
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package io.cucumber.cdi2;
2+
3+
import io.cucumber.java.api.en.Given;
4+
5+
import javax.enterprise.inject.Vetoed;
6+
import javax.inject.Inject;
7+
8+
@Vetoed
9+
public class BellyStepdefs {
10+
11+
@Inject
12+
private Belly belly;
13+
14+
@Given("I have {int} cukes in my belly")
15+
public void haveCukes(int n) {
16+
belly.setCukes(n);
17+
}
18+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package io.cucumber.cdi2;
2+
3+
import io.cucumber.java.api.en.Then;
4+
5+
import javax.enterprise.context.ApplicationScoped;
6+
import javax.inject.Inject;
7+
8+
import static org.junit.Assert.assertEquals;
9+
10+
@ApplicationScoped
11+
public class CDIBellyStepdefs {
12+
13+
@Inject
14+
private Belly belly;
15+
16+
@Then("there are {int} cukes in my belly")
17+
public void checkCukes(int n) {
18+
assertEquals(n, belly.getCukes());
19+
}
20+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package io.cucumber.cdi2;
2+
3+
import io.cucumber.core.backend.ObjectFactory;
4+
import org.junit.Test;
5+
6+
import static org.junit.Assert.assertEquals;
7+
import static org.junit.Assert.assertNotEquals;
8+
import static org.junit.Assert.assertNotNull;
9+
import static org.junit.Assert.assertNotSame;
10+
11+
public class Cdi2FactoryTest {
12+
13+
@Test
14+
public void shouldGiveUsNewInstancesForEachScenario() {
15+
16+
final ObjectFactory factory = new Cdi2Factory();
17+
factory.addClass(BellyStepdefs.class);
18+
factory.addClass(CDIBellyStepdefs.class);
19+
20+
// Scenario 1
21+
factory.start();
22+
final BellyStepdefs o1 = factory.getInstance(BellyStepdefs.class);
23+
final CDIBellyStepdefs cdiStep = factory.getInstance(CDIBellyStepdefs.class);
24+
assertNotEquals(CDIBellyStepdefs.class, cdiStep.getClass()); // it is a CDI proxy
25+
assertEquals(CDIBellyStepdefs.class, cdiStep.getClass().getSuperclass());
26+
factory.stop();
27+
28+
// Scenario 2
29+
factory.start();
30+
final BellyStepdefs o2 = factory.getInstance(BellyStepdefs.class);
31+
factory.stop();
32+
33+
assertNotNull(o1);
34+
assertNotSame(o1, o2);
35+
}
36+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package io.cucumber.cdi2;
2+
3+
import io.cucumber.junit.api.Cucumber;
4+
import org.junit.runner.RunWith;
5+
6+
@RunWith(Cucumber.class)
7+
public class RunCukesTest {
8+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package io.cucumber.cdi2;
2+
3+
import io.cucumber.java.api.Before;
4+
import io.cucumber.java.api.en.Given;
5+
6+
public class UnusedGlue {
7+
public UnusedGlue() {
8+
throw new IllegalStateException();
9+
}
10+
11+
@Given("unused")
12+
public void unused() {
13+
throw new IllegalStateException();
14+
}
15+
16+
@Before("@unused")
17+
public void unusedHook() {
18+
throw new IllegalStateException();
19+
}
20+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<beans xmlns="http://java.sun.com/xml/ns/javaee"
2+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xsi:schemaLocation="
4+
http://java.sun.com/xml/ns/javaee
5+
http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
6+
7+
</beans>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
Feature: Cukes
2+
3+
Scenario: Eat some cukes
4+
Given I have 4 cukes in my belly
5+
Then there are 4 cukes in my belly
6+
7+
Scenario: Eat some more cukes
8+
Given I have 6 cukes in my belly
9+
Then there are 6 cukes in my belly
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package io.cucumber.core.exception;
2+
3+
import java.util.Collections;
4+
import java.util.List;
5+
6+
public class CompositeCucumberException extends CucumberException {
7+
private final List<Throwable> causes;
8+
9+
public CompositeCucumberException(List<Throwable> causes) {
10+
super(String.format("There were %d exceptions:", causes.size()));
11+
this.causes = causes;
12+
}
13+
14+
public List<Throwable> getCauses() {
15+
return Collections.unmodifiableList(this.causes);
16+
}
17+
18+
public String getMessage() {
19+
StringBuilder sb = new StringBuilder(super.getMessage());
20+
for (Throwable e : this.causes) {
21+
sb.append(String.format("\n %s(%s)", e.getClass().getName(), e.getMessage()));
22+
}
23+
return sb.toString();
24+
}
25+
}

0 commit comments

Comments
 (0)