The JSR299/CDI(context-dependency-injection) is now part of any JavaEE6 application server, and I have had been exploring it on one such app-server Weblogic 12c, which bundles Weld 1.1.3.SP1 as the CDI container.
In JSF world, they say, it is a good practice to use appropriate scope on JSF managed-beans to make efficient use of the server-memory, and that the same applies to CDI managed-beans. For CDI beans, the supported scopes are @RequestScoped, @SessionScoped, @ApplicationScoped, and @ConversationScoped. However, there is no support in CDI for a JSF equivalent @ViewScoped bean, which happens to be the best choice in certain use cases.
So what do we do if we want @ViewScoped added to CDI managed-beans? The answer in my search so far is: cdi-extensions. The seam-faces module from JBoss is one such CDI extension that adds the @ViewScoped support. One simply needs to add the seam-faces module jars to the web or enterprise archive and the @ViewScoped is added automagically.
The auto magic part is that the seam3 modules are BDAs(bean-deployment-archives), jars that contain META-INF/beans.xml file, and therefore they are scanned for beans in the CDI bootstrap. The seam-faces module has dependencies on other seam-modules such as seam-international and those jars are also needed. A recommendation if you are using maven is to add a dependency management to seam-BOM(bill-of-material) and you would get all the needed dependencies, tested version jars etc. That's it per the JBoss documentation on getting the seam-faces working.
--snip--
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<seam.version>3.0.0.Final</seam.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.jboss.seam</groupId>
<artifactId>seam-bom</artifactId>
<version>${seam.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.jboss.seam.faces</groupId>
<artifactId>seam-faces</artifactId>
</dependency>
........
</dependencies>
In JSF world, they say, it is a good practice to use appropriate scope on JSF managed-beans to make efficient use of the server-memory, and that the same applies to CDI managed-beans. For CDI beans, the supported scopes are @RequestScoped, @SessionScoped, @ApplicationScoped, and @ConversationScoped. However, there is no support in CDI for a JSF equivalent @ViewScoped bean, which happens to be the best choice in certain use cases.
So what do we do if we want @ViewScoped added to CDI managed-beans? The answer in my search so far is: cdi-extensions. The seam-faces module from JBoss is one such CDI extension that adds the @ViewScoped support. One simply needs to add the seam-faces module jars to the web or enterprise archive and the @ViewScoped is added automagically.
The auto magic part is that the seam3 modules are BDAs(bean-deployment-archives), jars that contain META-INF/beans.xml file, and therefore they are scanned for beans in the CDI bootstrap. The seam-faces module has dependencies on other seam-modules such as seam-international and those jars are also needed. A recommendation if you are using maven is to add a dependency management to seam-BOM(bill-of-material) and you would get all the needed dependencies, tested version jars etc. That's it per the JBoss documentation on getting the seam-faces working.
--snip--
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<seam.version>3.0.0.Final</seam.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.jboss.seam</groupId>
<artifactId>seam-bom</artifactId>
<version>${seam.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.jboss.seam.faces</groupId>
<artifactId>seam-faces</artifactId>
</dependency>
........
</dependencies>
--snip--
In reality however, getting seam-faces to work on Weblogic 12c wasn't an easy experience. It failed with a number of ClassNotFound Exceptions despite using the BOM dependency. It seemed to presume the app-server to contain some seam-classes. That wasn't the case for weblogic, and adding explicit dependencies to the pom helped get past this issue.
Next it failed due to unsatisfied CDI dependencies with exception as follows:
Next it failed due to unsatisfied CDI dependencies with exception as follows:
--snip--
Caused By: org.jboss.weld.exceptions.DeploymentException: WELD-001408 Unsatisfied dependencies for type [Messages] with qualifiers [@Default] at injection point [[parameter 2] of [method] org.jboss.seam.faces.status.MessagesAdapter.convert(PhaseEvent, Messages)]
at org.jboss.weld.bootstrap.Validator.validateInjectionPoint(Validator.java:258)
at org.jboss.weld.bootstrap.Validator.validateObserverMethods(Validator.java:484)
at org.jboss.weld.bootstrap.Validator.validateDeployment(Validator.java:314)
at org.jboss.weld.bootstrap.WeldBootstrap.validateBeans(WeldBootstrap.java:361)
at com.oracle.injection.provider.weld.WeldInjectionContainer.start(WeldInjectionContainer.java:105)
--snip--
Above exception indicates a problem satisfying an injection-point inside MessagesAdapter bean inside seam-faces. It seems to inject "Messages" bean into MessagesAdapter and fails to find the "Messages" bean. Interestingly, the "Messages" bean is defined inside seam-international module and that was part of the deployment-archive, but still it didn't find the bean. So after some deliberation and a separate test, I concluded that there is a problem/bug in Weblogic 12c that cyclic dependencies across BDAs are not satisfied.
In other words, if you have two BDAs as part of a test.war: a.jar and b.jar, added in WEB-INF/lib, and then trying to inject a bean from a.jar into a class in b.jar doesn't work. This is needed per the JSR 299 specification. However, there is no problem in resolving beans inside the same BDA. So what's a workaround? Merge the two jars: a.jar and b.jar into a single jar and add that one to test.war.
Here is a way to create an uber jar of seam-faces and seam-international using maven:
Here is a way to create an uber jar of seam-faces and seam-international using maven:
--snip--
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.suhas.commonjar</groupId>
<artifactId>seamfaces-n-seami18n</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>seamfaces-n-seami18n</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>org.jboss.seam.faces</groupId>
<artifactId>seam-faces</artifactId>
<version>3.0.0.Final</version>
</dependency>
<dependency>
<groupId>org.jboss.seam.international</groupId>
<artifactId>seam-international</artifactId>
<version>3.0.0.Final</version>
</dependency>
<dependency>
<groupId>org.jboss.seam.solder</groupId>
<artifactId>seam-solder</artifactId>
<version>3.0.0.Final</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals><goal>shade</goal></goals>
</execution>
</executions>
<configuration>
<finalName>uber-${artifactId}-${version}</finalName>
</configuration>
</plugin>
</plugins>
</build>
</project>
--snip--
With above uber jar in the deployment-archive instead of seam-faces and seam-international helped resolve the CDI unsatisfied-dependencies problem, and now we have seam-faces working on 12c.
In summary, if you run into unsatisfied-dependencies problem on Weblogic 12c across two library BDAs, then see if creating an uber jar workaround may be be acceptable.
In summary, if you run into unsatisfied-dependencies problem on Weblogic 12c across two library BDAs, then see if creating an uber jar workaround may be be acceptable.
Hello! Great post, thanks! But, i can't retry your path :( May be you sharing your example war, what good deploy to weblogic 12c. Thank you! :)
ReplyDelete