CDI Reference Implementation: WELD

 

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)

This entry was posted in cdi. Bookmark the permalink.

One Response to CDI Reference Implementation: WELD

  1. Pingback: ?Weblogic 10.3.6? Weld – FIXBBS

Leave a Reply

Your email address will not be published. Required fields are marked *


*

This site uses Akismet to reduce spam. Learn how your comment data is processed.