【问题标题】:Using JSF and Spring 3, the BO is always null (when using an interface on your BO) [duplicate]使用 JSF 和 Spring 3,BO 始终为空(在 BO 上使用接口时)[重复]
【发布时间】:2016-12-01 21:26:00
【问题描述】:

我有一个简单的 hello world 应用程序,它使用 JSF 和 Spring 和 Maven。每当我从我的托管 Bean 中调用我的 BO(业务对象)时,BO 始终为空。我不确定我错过了什么或不理解什么。

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

希望在我的机器上查看整个应用程序的人的来源。

对于遇到问题的人,代码块将保持原样。我将在其下方发布我为使其正常工作所做的更改。

工作解决方案

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);
    }
}

在 pom.xml 中添加了以下依赖项

<dependency>
    <groupId>javax.inject</groupId>
    <artifactId>javax.inject</artifactId>
    <version>1</version>
</dependency>

【问题讨论】:

标签: spring jsf


【解决方案1】:

如果您希望 Spring 注入业务对象,则必须为 JSF 提供一些方法来解析 bean 引用。您的托管 bean 必须在将在 JSF 生命周期期间调用的方法中的某处初始化业务对象。

例如,这里是一个简单示例的相关部分。

首先,您需要在 Web 应用程序描述符中设置 Spring:

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

然后您需要使用解析器设置 JSF,让它在其托管 bean 中注入 Spring bean。

faces-config.xml

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

然后,您可以在托管 bean 中注入 Spring 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

请注意,我已使用 javax.inject 中的 @Named 注解在 Spring 配置中声明 bean,但此技术适用于任何 Spring 注入注解。

【讨论】:

  • 所以我尝试初始化业务对象,但 spring 不允许我按预期初始化它。我尝试了 HelloWorldBo helloWorldBo = new HelloWorldBo();那没有用。
  • 我已经将该行包含在我的 faces-config.xml 中,但它仍然不起作用。我最初有一个 post 构造,但在我的初始化方法上但删除了它以尝试隔离我的问题。
  • 我刚刚编辑了我的答案,以显示一个简单示例的完整配置链。希望对您有所帮助!
  • 感谢您抽出宝贵时间提供详细信息。我束手无策,试图弄清楚我不理解的是什么。我将审查您的编辑并与您联系。我已经创建了一个 helloSpring 项目,我一个人就可以使用它,但是在我的新项目中使用 spring 3 实现 jsf 2.2 很让人头疼。
  • 从您刚刚发布的源代码中,我想说您没有为 Spring 配置提供任何方式来构造和注入 BO bean。您需要特别注意 @ManagedProperty(value = "#{dummyService}")、@Named("dummyService") 和 在我的示例中处理注释。
猜你喜欢
  • 1970-01-01
  • 2011-06-05
  • 2016-05-09
  • 2015-01-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多