1

I was using @ManagedBean and try to change to CDI @Named as the former one will be deprecated.

As soon as I changed one of my controller class to use CDI, I hit the exception saying the controller is resolved to null.

I have googled many posts regarding this issue, read as many as I can, however, seems nothing could help me out so far, please kindly advise on my case. (also tried to remove lib/javax.inject-1.jar as one of the post suggested, but no luck.)

  1. I got the GF4 start up in NB 7.4.
  2. Deploy my app without any error.
  3. Access pages without error except that all variable texts are blank since they are set in the controller and load using value="#{xxxController.someText}".
  4. I click the submit button and the null controller error pops out from the console log due to input variables are set using value="#{userController.user.username}" like expression.

Env:

NetBeans 7.4
Glassfish 4
JDK 1.7

pom:

 <dependencies>

<!-- MySQL Connector -->
<dependency>
  <groupId>mysql</groupId>
  <artifactId>mysql-connector-java</artifactId>
  <version>5.1.28</version>
  <scope>provided</scope>
</dependency>

<!-- Hibernate -->
<dependency>
  <groupId>org.hibernate</groupId>
  <artifactId>hibernate-core</artifactId>
  <version>4.2.8.Final</version>
</dependency>
<dependency>
  <groupId>org.hibernate</groupId>
  <artifactId>hibernate-entitymanager</artifactId>
  <version>4.2.8.Final</version>
</dependency>

<!-- JSF -->
<dependency>
  <groupId>org.glassfish</groupId>
  <artifactId>javax.faces</artifactId>
  <version>2.2.5</version>
</dependency>

<!-- JSTL -->
<dependency>
  <groupId>jstl</groupId>
  <artifactId>jstl</artifactId>
  <version>1.2</version>
</dependency>

<!-- PrimeFaces -->
<dependency>
  <groupId>org.primefaces</groupId>
  <artifactId>primefaces</artifactId>
  <version>4.0</version>
</dependency>
<dependency>
  <groupId>org.primefaces.themes</groupId>
  <artifactId>all-themes</artifactId>
  <version>1.0.10</version>
</dependency>

<!-- Security -->
<dependency>
  <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-core</artifactId>
  <version>1.2.3</version>
</dependency>
<dependency>
  <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-web</artifactId>
  <version>1.2.3</version>
</dependency>

<!-- Commons -->
<dependency>
  <groupId>org.apache.commons</groupId>
  <artifactId>commons-lang3</artifactId>
  <version>3.2.1</version>
</dependency>
<dependency>
  <groupId>commons-logging</groupId>
  <artifactId>commons-logging</artifactId>
  <version>1.1.3</version>
</dependency>

<!-- CDI -->
<dependency>
    <groupId>javax.enterprise</groupId>
    <artifactId>cdi-api</artifactId>
    <version>1.1</version>
</dependency>

<!-- Logger -->
<dependency>
  <groupId>org.slf4j</groupId>
  <artifactId>slf4j-api</artifactId>
  <version>1.7.6</version>
</dependency>
<dependency>
  <groupId>org.apache.logging.log4j</groupId>
  <artifactId>log4j-api</artifactId>
  <version>2.0-rc1</version>
</dependency>
<dependency>
  <groupId>org.apache.logging.log4j</groupId>
  <artifactId>log4j-core</artifactId>
  <version>2.0-rc1</version>
</dependency>
<dependency>
  <groupId>org.apache.logging.log4j</groupId>
  <artifactId>log4j-slf4j-impl</artifactId>
  <version>2.0-rc1</version>
</dependency>

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app 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/web-app_3_0.xsd" 
version="3.0">

beans.xml:

<?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>

faces-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<faces-config 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/web-facesconfig_2_2.xsd"
              version="2.2">
</faces-config>

the controller class looks like:

import javax.enterprise.context.SessionScoped;
import javax.inject.Named;

@Named
@SessionScoped
public class UserController implements Serializable {

xhtml calling bean:

<h:outputText value="Username: " />
  <p:inputText value="#{userController.user.username}">
</p:inputText>

maven folder structure followed with:

WEB-INF
--beans.xml
--faces-config.xml
--glassfish-web.xml
--web.xml

2014 Mar 14: Found out the controller's constructor never called while using CDI. No problem at all when using @ManagedBean.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
HxHxH
  • 11
  • 3
  • Please post the content of your faces-config.xml file. – Luiggi Mendoza Mar 13 '14 at 16:24
  • Found out the controller's constructor never called while using CDI. No problem at all when using @ManagedBean. – HxHxH Mar 14 '14 at 12:31
  • Don't use the constructor to place business logic in your beans. Use `@PostConstruct` on a `public void` method instead. – Luiggi Mendoza Mar 14 '14 at 14:51
  • I did use @PostConstruct, but since nothing worked, so I added loggings in both constructor and postConstruct, that's how I found out the constructor never called under CDI. – HxHxH Mar 14 '14 at 15:14
  • It would be better if you post an answer based on what you've found. I cannot recall where I read that the logic inside bean constructor may not be invoked but the logic in `@PostConstruct` method is guaranteed to be invoked. – Luiggi Mendoza Mar 14 '14 at 15:26

2 Answers2

0

You're victim of classpath pollution and confusion with online tutorials/examples targeted at a non-Java EE container, such as Tomcat. GlassFish is a true Java EE container which already bundles among others JSF and CDI out the box, yet your pom.xml instructs Maven to bundle another ones along with the webapp which is only necessary on a non-Java EE container, such as Tomcat:

<!-- JSF -->
<dependency>
    <groupId>org.glassfish</groupId>
    <artifactId>javax.faces</artifactId>
    <version>2.2.5</version>
</dependency>

<!-- CDI -->
<dependency>
    <groupId>javax.enterprise</groupId>
    <artifactId>cdi-api</artifactId>
    <version>1.1</version>
</dependency>

This is not right. This will end up in duplicate JSF and CDI libraries in the runtime classpath which only collides with each other and has your problem as one of the consequences.

You need to mark them as <scope>provided</scope>, which should tell Maven that the target environment (in your case: GlassFish) has them already bundled, so that Maven won't bundle them in the WAR.

<!-- JSF -->
<dependency>
    <groupId>org.glassfish</groupId>
    <artifactId>javax.faces</artifactId>
    <version>2.2.5</version>
    <scope>provided</scope>
</dependency>

<!-- CDI -->
<dependency>
    <groupId>javax.enterprise</groupId>
    <artifactId>cdi-api</artifactId>
    <version>1.1</version>
    <scope>provided</scope>
</dependency>

The same problem applies to that JSTL dependency, by the way, but this is beyond the question's scope.

An alternative is to get rid of them all (JSF, CDI and JSTL) and just specify the full provided Java EE web profile dependency (which also includes another Java EE awesomeness, such as EJB and JPA).

<!-- Java EE 7 web profile -->
<dependency>
    <groupId>javax</groupId>
    <artifactId>javaee-web-api</artifactId>
    <version>7.0</version>
    <scope>provided</scope>
</dependency>

This way you don't need to declare every already-bundled Java EE artifact individually as compile time dependency.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
-1

Sounds like your 'user' object is not instanced correctly. Try this in it's GET method in your controller class:

public User getUser() {
   if (user == null) {
      user = new User();
   }
   return user;
} 

Hope this can help you, if not, please post both your entity and DAO class for 'User'.

N0nbot
  • 190
  • 1
  • Found out the controller's constructor never called while using CDI. No problem at all when using @ManagedBean. – HxHxH Mar 14 '14 at 12:30
  • The getters should be as clean as they can. You should avoid having any logic in them in your managed beans. If you need to initialize any variable, do it in `@PostConstruct` method instead. – Luiggi Mendoza Mar 14 '14 at 15:15