DI is unthinkable these days. Having different variations on the same concept in different classes and of course a separate context for testing. Although for testing mocking instead of stubbing is also a very valid option. I have been playing around with Spring and with Google guice but I never came around to play with CDI. I have been playing with it today And I must say it is quiet charming. I really loved the simple and direct way of annotating stuff and no traces of xml files (only if you want too).
The part I want to describe is the part to use for testing. It reminds me a lot of how that works with spring apart from the fact that I did not had to point to a context.xml file.
The example:
Because the jsr 299 is a reference, the main parties allready have build there implementation for it :
(The versions are at this point in time (march 2014) the latest.
- JBoss it would be:
<dependency>
<groupId>org.jboss.weld</groupId>
<artifactId>weld-core</artifactId>
<version>2.2.0.Beta1</version>
</dependency>
<dependency>
<groupId>org.jboss.spec</groupId>
<artifactId>jboss-javaee-6.0</artifactId>
<version>1.0.0.Final</version>
<type>pom</type>
<scope>provided</scope>
</dependency>
- Apache
<dependency>
<groupId>org.apache.openwebbeans</groupId>
<artifactId>openwebbeans-impl</artifactId>
<version>1.2.2</version>
</dependency>
To write a piece of code that chooses the depedency for its needs CDI is great in being simple:
The interface that makes the difference:
public interface IHelloWorld {
void sayHello();
}
The class that does my realtime serious business kind of logic:
import javax.enterprise.inject.Alternative;
//This annotation tells the CDI container that it is one of the many implementations.
@Alternative
public class HelloWorld implements IHelloWorld {
public void sayHello() {
System.out.println("Hello world");
}
}
The class that does my very serious alternative kind of business logic or test stubbing.
import javax.enterprise.inject.Alternative;
//This annotation tells the CDI container that it is one of the many implementations.
@Alternative
public class HelloAlternative implements IHelloWorld {
public void sayHello() {
System.out.println("hello alternative world");
}
The class that is complete unaware of the fact that he does not speak to the same injected all the time. Love to keep this one in the dark about that.
import javax.inject.Inject;
public class LoginBean {
//This is the actual injection of the desired class.
@Inject
private IHelloWorld helloWorld;
public void print() {
helloWorld.sayHello();
}
}
The first test that uses my very serious business logic saying: "Hello world "
import javax.inject.Inject;
import org.jglue.cdiunit.ActivatedAlternatives;
import org.jglue.cdiunit.CdiRunner;
import org.junit.Test;
import org.junit.runner.RunWith;
//The annotation that hooks this test up with te CDI container
@RunWith(CdiRunner.class)
// The annotation that tells which implementation of the IHelloWorld Interf to use.
@ActivatedAlternatives(HelloWorld.class)
public class HelloWorldTest {
//Injects the bean that has a DI itself.
@Inject
LoginBean loginBean;
@Test
public void test() {
loginBean.print();
//outcome : "Hello world"
}
import javax.inject.Inject;
import org.jglue.cdiunit.ActivatedAlternatives;
import org.jglue.cdiunit.CdiRunner;
import org.junit.Test;
import org.junit.runner.RunWith;
//The annotation that hooks this test up with te CDI container
@RunWith(CdiRunner.class)
// The annotation that tells which implementation of the IHelloWorld Interf to use.
@ActivatedAlternatives(HelloWorld.class)
public class HelloAlternativeTest {
@Inject
LoginBean loginBean;
@Test
public void test() {
loginBean.print();
//outcome: hello alternative world
}
At last but not least the full Apache maven tech stack:
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.3</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>javax.enterprise</groupId>
<artifactId>cdi-api</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>org.jglue.cdi-unit</groupId>
<artifactId>cdi-unit</artifactId>
<version>2.1.0</version>
<scope></scope>
</dependency>
And the full JBoss maven tech stack:
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.3</version>
</dependency>
<dependency>
<groupId>javax.enterprise</groupId>
<artifactId>cdi-api</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>6.0</version>
</dependency>
<dependency>
<groupId>org.jglue.cdi-unit</groupId>
<artifactId>cdi-unit</artifactId>
<version>2.1.0</version>
</dependency>
<dependency>
<groupId>org.jboss.weld</groupId>
<artifactId>weld-core</artifactId>
<version>2.2.0.Beta1</version>
</dependency>
<dependency>
<groupId>org.jboss.spec</groupId>
<artifactId>jboss-javaee-6.0</artifactId>
<version>1.0.0.Final</version>
<type>pom</type>
<scope>provided</scope>
</dependency>
Conclusion:
If you are using the Apache stack and you want to move to the JBoss stack or visa versa, that does not mather. They bot comply to the JSR 299. There is no need for code changing. To me personal this way of DI is more intuitive and very powerfull by the annotatons it is using. Give it a try and let me know what you think of it.
Have fun!
Geen opmerkingen:
Een reactie posten