-1

What I have is a simple hello world application utilizing JSF and Spring with Maven. Whenever I call on my BO (business object) from within my Managed Bean the BO is always null. I am not sure what I am missing or not understanding.

HelloWorldMB.java

package com.project.web;

import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;

import tech.calvanodesign.business.HelloWorldBo;

import java.io.Serializable;

@ManagedBean
@SessionScoped
public class HelloWorldMB implements Serializable {

    public HelloWorldBo helloWorldBo;

    private static final long serialVersionUID = 1L;

    private String name;

    public void init () {
        System.out.println("HelloWorldMB.init()");
        if (helloWorldBo != null)
            return;
        System.out.println("helloWorldBo is null");
    }

    public String springTest() {
        // Call the business object to register the user
        helloWorldBo.springTest(name);
        return "";
    }

    // Set the registrationBo attribute used by Spring
    public void setHelloWorldBo(HelloWorldBo helloWorldBo) {
        this.helloWorldBo = helloWorldBo;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

welcome.xhtml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"    
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:p="http://primefaces.org/ui">

<h:head>
    <title>JSF 2.0 Hello World</title>
    <h:outputStylesheet library="css" name="style.css" />
</h:head>
<h:body>
    <h:form>
        <p:growl id="growl" showDetail="true" sticky="true" />  
            <p:inputText id="intxtSpringTest" value="#{helloWorldMB.name}"/>
            <p:commandButton id="cmdbtnSpringTest" value="Test Spring 3 with JSF" action="#{helloWorldMB.springTest}" ajax="false"/>
        </p:panel>
    </h:form>
</h:body>

HelloWorldBo.java

package com.project.business;

public interface HelloWorldBo {
    /**
     * springTest method
     * @param name
     */
    public void springTest(String name); 
}

HelloWorldBoImpl

package com.project.business;

public class HelloWorldBoImpl implements HelloWorldBo {

    /**
     * Tests the spring and jsf implementation
     */
    @Override
    public void springTest(String name) {
        System.out.println("HelloWorldBoImpl:: springTest : " + name);
    }
}

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

    <application>
        <el-resolver>
                org.springframework.web.jsf.el.SpringBeanFacesELResolver
        </el-resolver>
    </application>

</faces-config>

pom.xml

<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>tech.calvanodesign</groupId>
<artifactId>calvanodesignsource</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>calvanodesignsource Maven Webapp</name>
<url>http://maven.apache.org</url>
<dependencies>

<dependency>
    <groupId>com.sun.faces</groupId>
    <artifactId>jsf-api</artifactId>
    <version>2.1.7</version>
</dependency>
<dependency>
    <groupId>com.sun.faces</groupId>
    <artifactId>jsf-impl</artifactId>
    <version>2.1.7</version>
</dependency>

<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>servlet-api</artifactId>
    <version>2.5</version>
    <scope>provided</scope>
</dependency>

<dependency>
    <groupId>javax.servlet.jsp</groupId>
    <artifactId>jsp-api</artifactId>
    <version>2.1</version>
    <scope>provided</scope>
</dependency>

 <dependency>
     <groupId>commons-logging</groupId>
     <artifactId>commons-logging</artifactId>
     <version>1.1.1</version>
 </dependency>

 <dependency>
     <groupId>commons-lang</groupId>
     <artifactId>commons-lang</artifactId>
     <version>2.6</version>
 </dependency>

<dependency>
  <groupId>junit</groupId>
  <artifactId>junit</artifactId>
  <version>3.8.1</version>
  <scope>test</scope>
</dependency>

<dependency>  
    <groupId>org.primefaces</groupId>  
    <artifactId>primefaces</artifactId>  
    <version>6.0</version>  
</dependency>

        <!-- spring-context which provides core functionality -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>4.2.5.RELEASE</version>
</dependency>

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-web</artifactId>
    <version>4.2.5.RELEASE</version>
</dependency>
  </dependencies>
    <build>
       <finalName>calvanodesignsource</finalName>
           <plugins>
               <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.1</version>
                    <configuration>
                        <source>1.8</source>
                        <target>1.8</target>
                    </configuration>
                </plugin>
            </plugins>
      </build>
    </project>

https://github.com/Epooch/CalvanoDesignSource

The source for those who want to see the whole application as it is on my machine.

The code blocks will remain as it was for those who run into the issues. I will post below it the changes that I had made to make it work.

Working Solution

HelloWorldMB

package com.project.web;

import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;

import com.project.business.HelloWorldBo;

import java.io.Serializable;

@ManagedBean
@SessionScoped
public class HelloWorldMB implements Serializable {

    @ManagedProperty(value = "#{helloWorldBo}")
    private HelloWorldBo helloWorldBo;

    private static final long serialVersionUID = 1L;

    private String name;

    public void init () {
        System.out.println("HelloWorldMB.init()");
        if (helloWorldBo != null)
            return;
        System.out.println("helloWorldBo is null");
    }

    public void springTest(ActionEvent e) {
        // Call the business object to register the user
        helloWorldBo.springTest(name);
    }

    // Set the registrationBo attribute used by Spring
    public void setHelloWorldBo(HelloWorldBo helloWorldBo) {
        this.helloWorldBo = helloWorldBo;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

HelloWorldBo

package com.project.business;

public interface HelloWorldBo {
    /**
     * springTest method
     * @param name
     */
    public void springTest(String name); 
}

HelloWorldBoImpl

package com.project.business;
import javax.inject.Named;

@Named("helloWorldBo")
public class HelloWorldBoImpl implements HelloWorldBo {

    /**
     * Tests the spring and jsf implementation
     */
    @Override
    public void springTest(String name) {
        System.out.println("HelloWorldBoImpl:: springTest : " + name);
    }
}

Added the following dependency to the pom.xml

<dependency>
    <groupId>javax.inject</groupId>
    <artifactId>javax.inject</artifactId>
    <version>1</version>
</dependency>
Eric
  • 699
  • 5
  • 15

1 Answers1

1

If you expect Spring to inject the business object, you will have to provide JSF with some way to resolve the bean references. Your managed bean must initialize the business object somewhere in a method that will be invoked during the JSF lifecycle.

For example, here are the relevant sections from a simple example.

First, you need the Spring setup in the web application descriptors:

/WEB-INF/web.xml

<web-app>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            /WEB-INF/app-service-config.xml
        </param-value>
    </context-param>
    <listener>
        <listener-class>
            org.springframework.web.context.ContextLoaderListener
        </listener-class>
    </listener>
    <listener>
         <listener-class>
             org.springframework.web.context.request.RequestContextListener
         </listener-class>
    </listener>

/WEB-INF/app-service-config.xml

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- Spring 3.1 annotation support -->
    <context:component-scan base-package="com.rtt.simple.service" />

Then you need to set up JSF with a resolver that lets it inject Spring beans in its managed beans.

faces-config.xml

<application>
    <!-- Spring Framework support -->
    <el-resolver>
        org.springframework.web.jsf.el.SpringBeanFacesELResolver
    </el-resolver>

Then, you can inject a Spring bean in a managed bean:

DummyBackingBean.java

@ManagedBean
@ViewScoped
public class DummyBackingBean implements Serializable {

@ManagedProperty(value = "#{dummyService}")
private DummyService dummyService;

private List<DummyDataItem> dataItems;

@PostConstruct
public void postConstruct() {
    LOG.trace("postConstruct()");

    dataItems = dummyService.listAll();
}

public DummyService getDummyService() {
    return dummyService;
}

public void setDummyService(DummyService dummyService) {
    this.dummyService = dummyService;
}

DummyService.java

package com.rtt.simple.service;

import javax.inject.Named;
import com.rtt.simple.domain.DummyDataItem;

@Named("dummyService")
public class DummyService {

    private static List<DummyDataItem> dataItems;

    public List<DummyDataItem> listAll() {
        return dataItems;
    }

    static {
        dataItems = new ArrayList<DummyDataItem>();

        // Initialize the dataItems list with static data

Note that I've used the @Named annotation from javax.inject to declare the bean in the Spring configuration, but this technique will work with any Spring injection annotation.

Dave Curry
  • 176
  • 1
  • 5
  • So I have tried to initialize the business object but spring didn't allow me to initialize it as I would have expected. I attempted the HelloWorldBo helloWorldBo = new HelloWorldBo(); That did not work. – Eric Jul 27 '16 at 18:23
  • I had already included that line in my faces-config.xml and it still doesn't function. I originally had a post construct but on my initialization method but removed it to try and isolate my issue. – Eric Jul 27 '16 at 18:35
  • I just edited my answer to show the complete configuration chain for a simple example. Hope it helps! – Dave Curry Jul 27 '16 at 19:12
  • thank you for taking the time to include that level of detail. I am at my wits end trying to figure out what it is that I am not understanding. I am going to review your edits and follow up with you. I have created a helloSpring project and alone I am able to use it but in my new project to implement jsf 2.2 with spring 3 it's been a headache. – Eric Jul 27 '16 at 19:17
  • From the source you just posted, I'd say that you haven't provided any way for the Spring configuration to construct and inject the BO bean. You'll want to pay particular attention to the @ManagedProperty(value = "#{dummyService}"), @Named("dummyService"), and annotation handling in my example. – Dave Curry Jul 27 '16 at 19:49
  • Even after using the ManagedProperty and Named annotations [the context:component-scan base-package was already present]. My Bo is still null. – Eric Jul 27 '16 at 20:08
  • Resolved!!!!! Dan you are the man, I placed the named annotation on the interface of HelloWorldBo rather than HelloWorldBoImpl. Once I got that everything snapped in place!!!!! – Eric Jul 27 '16 at 20:17