Tomcat üzerinde CDI kullanmak istiyorsanız Weld kütüphanesini kullanabilirsiniz. Bunun için aşağıdakileri yapmanız gerekir.
Gerekli kütüphaneleri aşağıdaki gibi ekleyelim
<dependency>
<groupId>javax.enterprise</groupId>
<artifactId>cdi-api</artifactId>
<version>1.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jboss.weld.servlet</groupId>
<artifactId>weld-servlet</artifactId>
<version>2.4.2.Final</version>
</dependency>
CDI API ve weld servlet kütüphanesi eklenmiştir.
Web.xml'e aşağıdaki gibi listener eklenir
<listener>
<listener-class>org.jboss.weld.environment.servlet.Listener</listener-class>
</listener>
Bean yönetimi için META-INF altına context.xml dosyası eklenir ve aşağıdakiler dosyaya yazılır:
<Context>
<Resource name="BeanManager"
auth="Container"
type="javax.enterprise.inject.spi.BeanManager"
factory="org.jboss.weld.resources.ManagerObjectFactory"/>
</Context>
Ardından burada tanımlanan BeanManager web.xml'e eklenir
<resource-env-ref>
<resource-env-ref-name>BeanManager</resource-env-ref-name>
<resource-env-ref-type>javax.enterprise.inject.spi.BeanManager</resource-env-ref-type>
</resource-env-ref>
WEB-INF klasörüne içi boş da olsa beans.xml dosyası eklenir
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
version="1.1" bean-discovery-mode="all">
</beans>
Artık CDI Tomcat'te kullanıma hazırdır. Aşağıdaki gibi deneme amaçlı bir Bean yaratalım
import javax.inject.Named;
@Named
public class Test {
public Test() {}
public String getMessage(){
return "Merhaba CDI Tomcat";
}
}
Bu bean'i bir Servlet'te inject ederek kullanalım
import java.io.IOException;
import javax.inject.Inject;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/TestServlet")
public class TestServlet extends HttpServlet {
@Inject
Test test;
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.getWriter().write(test.getMessage());
}
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
Web projesini çalıştırıp aşağıdaki gibi (web projenin path'i CdiTomcat) çağırdığımızda "Merhaba CDI Tomcat" cevap olarak dönülecektir.
http://localhost:8080/CdiTomcat/TestServlet
CDI'i JSF ile de kullanabilirsiniz. Ancak bunu yapmak için JSF'de kullanılan bean'leri @ManagedBean ile değil @Named ile işaretlemeniz gerekir. Aynı şekilde javax.enterprise.context içindeki scope'ları kullanmanız , JSF'nin scope'larını kullanmamanız gerekir.
JSF için gerekli bağımlılıkları ekleyelim
<dependency>
<groupId>com.sun.faces</groupId>
<artifactId>jsf-api</artifactId>
<version>2.2.14</version>
</dependency>
<dependency>
<groupId>com.sun.faces</groupId>
<artifactId>jsf-impl</artifactId>
<version>2.2.14</version>
</dependency>
Aşağıdaki gibi bir TestBean yapalım
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.inject.Named;
@Named
@RequestScoped
public class TestBean {
@Inject
Test test;
public TestBean() {}
public String getMessage(){
return test.getMessage();
}
}
Bu bean'i bir xhtml sayfasında kullanalım
<!DOCTYPE html>
<html xmlns:h="http://java.sun.com/jsf/html">
<head>
<meta charset="ISO-8859-9"/>
</head>
<body>
<h:outputLabel value="#{testBean.message}"></h:outputLabel>
</body>
</html>
Bu sayfa tarayıcıda çalıştığında ekranda "Merhaba CDI Tomcat" yazısı görülecektir.
NOT: CDI'da ViewScope bulunmaz. View Scope kullanmak için Omnifaces kütüphanesini kullanmanızı tavsiye ederim. Omnifaces CDI ile çalışan bir kütüphanedir.
CDI ve JUnit ile sunucuya (tomcat , jboss vb..) gerekli olmadan birim testleri yapılabilmektedir.
Bunun için junit ve weld se kütüphanesi bağımlılıklarını ekleyelim
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jboss.weld.se</groupId>
<artifactId>weld-se-core</artifactId>
<version>2.2.16.Final</version>
<scope>test</scope>
</dependency>
Test kodu yazabilmek için öncelikle bir WeldContext sınıfı ekleleyim
import org.jboss.weld.environment.se.Weld;
import org.jboss.weld.environment.se.WeldContainer;
public class WeldContext {
public static final WeldContext INSTANCE = new WeldContext();
private final Weld weld;
private final WeldContainer container;
private WeldContext() {
this.weld = new Weld();
this.container = weld.initialize();
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
weld.shutdown();
}
});
}
public <T> T getBean(Class<T> type) {
return container.instance().select(type).get();
}
}
Bu şekilde bean'leri yöneten bir sınıf yaratılmış olur.
Şimdi bir Junit testleri için Runner sınıfı yaratıyoruz:
import org.junit.runners.BlockJUnit4ClassRunner;
import org.junit.runners.model.InitializationError;
public class WeldJUnit4Runner extends BlockJUnit4ClassRunner {
public WeldJUnit4Runner(Class<Object> clazz) throws InitializationError {
super(clazz);
}
@Override
protected Object createTest() {
final Class<?> test = getTestClass().getJavaClass();
return WeldContext.INSTANCE.getBean(test);
}
}
Artık test sınıfını aşağıdaki gibi yazabiliriz:
import javax.inject.Inject;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(WeldJUnit4Runner.class)
public class MyUnitTest {
@Inject
com.test.Test testObj;
@Test
public void myTest(){
String message=testObj.getMessage();
Assert.assertEquals("Merhaba CDI Tomcat", message);
}
}
Görüldüğü gibi bizim yarattığımız Test sınıfı inject edilmiştir. Eğer classpath'in META-INF'de beans.xml yok ise aşağıdaki gibi bir hata alabilirsiniz :
Caused by: java.lang.IllegalStateException: WELD-ENV-000016: Missing beans.xml file in META-INF
at org.jboss.weld.environment.se.Weld.initialize(Weld.java:131)
at com.test.WeldContext.
(WeldContext.java:15)
at com.test.WeldContext.(WeldContext.java:8)
... 18 more
Bunu çözmek için beans.xml'i META-IF klasörüne (yok ise yaratılması gerekir) ekleyin :
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
version="1.1" bean-discovery-mode="all">
</beans>
Artık birim testiniz başarıyla çalışması gerekir.
Bu örnek http://memorynotfound.com/java-se-unit-testing-cdi-junit-jboss-weld-se sayfasından yararlanılarak yapılmıştır.