Contents
Download WELD
* Download Weld from http://seamframework.org/Weld/Downloads
* I downloaded weld-1.1.5.Final.zip
* Unzip into a local directory, e.g. c:\prog
Example
Setup Eclipse Project
* Start Eclipse, I used Indigo
* Create a new Dynamic Web Project named: test.cdi
* Click Finish button to create project
* Add weld-servlet.jar to project buildpath
* Also add MyFaces Core 2.0.11 and MyFaces Trinidad 2.0.0 user libraries to build path. See this post for how to setup these user libraries.
* Add both weld-servlet.jar, MyFaces Core 2.0.11, and MyFaces Trinidad 2.0.0 user libraries to Deployment Assembly
* Add to web.xml
<listener> <listener-class>org.jboss.weld.environment.servlet.Listener</listener-class> </listener>
* Also add to web.xml to enable JSF feature
<servlet> <servlet-name>JSF</servlet-name> <servlet-class>javax.faces.webapp.FacesServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>JSF</servlet-name> <url-pattern>/faces/*</url-pattern> </servlet-mapping>
* Final web.xml looks like this:
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <display-name>test.cdi</display-name> <welcome-file-list> <welcome-file>index.html</welcome-file> <welcome-file>index.htm</welcome-file> <welcome-file>index.jsp</welcome-file> <welcome-file>default.html</welcome-file> <welcome-file>default.htm</welcome-file> <welcome-file>default.jsp</welcome-file> </welcome-file-list> <servlet> <servlet-name>JSF</servlet-name> <servlet-class>javax.faces.webapp.FacesServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>JSF</servlet-name> <url-pattern>/faces/*</url-pattern> </servlet-mapping> <listener> <listener-class>org.jboss.weld.environment.servlet.Listener</listener-class> </listener> </web-app>
* Create a new folder named META-INF under src directory.
* Create an empty beans.xml in the newly created src/META-INF directory
Important note: you have to place beans.xml in src/META-INF in order for WELD to work in WebLogic 10.3.5. Placing beans.xml in WEB-INF directory works for Tomcat and JBoss but not WebLogic 10.3.5.
Create Java Classes
* Create a new package named hello
* Create a new Java class named Greeting1 with class annotation of @Named:
package hello; import javax.inject.Named; @Named public class Greeting1 { public String getGreet() { return "Hello, my friend, without injection"; } }
* Create another Java class named Greeting2 without annotation:
package hello; public class Greeting2 { public String getGreet(String name){ return "Hello, " + name + ", from injection."; } }
* Create a new Java class named GreetingService with class annotation of @Named. Also annotate to inject Greeting2 to GreetingService as shown below:
package hello; import javax.inject.Inject; import javax.inject.Named; @Named public class GreetingService { @Inject Greeting2 greeting; public String getGreet(){ return this.greeting.getGreet("my friend"); } }
Create a Test JSF Page
* Create a test JSF page named hello.xhtml
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html"> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/> <title>Insert title here</title> </head> <body> <b>Greet without injection:</b> #{greeting1.greet} <br/> <b>Greet from injection:</b> #{greetingService.greet} </body> </html>
Deploy and Test
* Project files:
Deploy to Tomcat 6 or 7
* Deploy to Tomcat 6 or 7
* Point browser to http://localhost:8080/test.cdi/faces/hello.xhtml. You should see both greetings with and without injection.
Deploy to WebLogic 11g R1
* You have to place beans.xml in src/META-INF. Place it in WEB-INF won’t work.
* You have to create a weblogic.xml in WEB-INF directory and set wls:prefer-web-inf-classes to true. Otherwise, WEB-INF/lib jar files won’t get loaded properly.
<?xml version="1.0" encoding="UTF-8"?> <wls:weblogic-web-app xmlns:wls="http://xmlns.oracle.com/weblogic/weblogic-web-app" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd http://xmlns.oracle.com/weblogic/weblogic-web-app http://xmlns.oracle.com/weblogic/weblogic-web-app/1.2/weblogic-web-app.xsd"> <wls:weblogic-version>10.3.5</wls:weblogic-version> <wls:context-root>test</wls:context-root> <wls:container-descriptor> <wls:prefer-web-inf-classes>true</wls:prefer-web-inf-classes> </wls:container-descriptor> </wls:weblogic-web-app>
* If you have third party jar files that are used in CDI injection, you need to add beans.xml to META-INF directory of the jar file in order for the jar file to be scanned by WebLogic for CDI bean classes.
* beans.xml needs to have the content:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/beans_1_0.xsd"> </beans>
* I deployed to JDev 11gR1 integrated WLS directly from Eclipse Indigo.
* Once deployed, point browser to http://localhost:7101/test/faces/hello.xhtml
Conversational Scope
@Named("usrMsgs") @ConversationScoped public class UserMessagesVO implements Serializable { @Inject Conversation conversation; private void reload(){ this.endConversation(); this.beginConversation(); this.setupUsrAccount(); } public void beginConversation() { if (conversation.isTransient()) { conversation.begin(); } } public void endConversation() { if (!conversation.isTransient()) { conversation.end(); } } }
CDI JUnit Testing
* Create a new Java class:
package test.util; import org.jboss.weld.environment.se.Weld; import org.jboss.weld.environment.se.WeldContainer; import org.junit.runners.BlockJUnit4ClassRunner; import org.junit.runners.model.InitializationError; public class WeldJUnit4Runner extends BlockJUnit4ClassRunner { private Class<?> klass; private Weld weld; private WeldContainer container; public WeldJUnit4Runner(Class<?> klass) throws InitializationError { super(klass); this.klass = klass; this.weld = new Weld(); this.container = weld.initialize(); } @Override protected Object createTest() throws Exception { return this.container.instance().select(this.klass).get(); } }
* Annotate test class
@RunWith(WeldJUnit4Runner.class) public class TestNotifications { }
Sample Code
* Sample code for this blog can be downloaded: test.cdi.
Issues
Singleton is not set when Open JSF Page
* Error message:
Caused by: java.lang.IllegalStateException - Singleton is not set at org.jboss.weld.bootstrap.api.helpers.IsolatedStaticSingletonProvider$IsolatedStaticSingleton.get(IsolatedStaticSingletonProvider.java:52)
* Possible cause: missing weld listener in web.xml
* Fix: add to web.xml
<listener> <listener-class>org.jboss.weld.environment.servlet.Listener</listener-class> </listener>
WELD-000101 Transactional services not available
* Error message:
232 [main] INFO org.jboss.weld.Bootstrap - WELD-000101 Transactional services not available. Injection of @Inject UserTransaction not available. Transactional observers will be invoked synchronously.
* Possible cause: META-INF/beans.xml missing
* Solution: Add META-INF/beans.xml missing to class path
Use Injected Beans in Constructor
* Don’t use injected bean instances in constructor since the injected beans have not been initialized hence nulls.
* Use @PostConstruct instead.
References
* The Java EE 6 Tutorial: Basic Concepts, Fourth Edition By: Eric Jendrock et al Chapter 17
* Weld – JSR-299 Reference Implementation
* Getting Started with JSF 2.0 and CDI in JEE 6 part 1
* CDI: Context and Dependency Injection (JSR-299)
Pingback: ?Weblogic 10.3.6? Weld – FIXBBS