JSF-2.3 找不到我的 @Named CDI-1.2 托管 bean

Posted

技术标签:

【中文标题】JSF-2.3 找不到我的 @Named CDI-1.2 托管 bean【英文标题】:JSF-2.3 not finding my @Named CDI-1.2 managed bean 【发布时间】:2017-10-19 06:51:22 【问题描述】:

最近从 2.2 升级到 JSF 2.3,我注意到 @ManagedBean 已被弃用,经过一些研究发现我应该使用 CDI-1.2 托管 bean 和 @Named 注释。

但是切换到@Named 后,JSF 页面找不到托管 bean:

javax.servlet.ServletException: /index.xhtml @38,38 value="#controller.telstraPass": 目标不可达,标识符“控制器”解析为空

我正在使用 Maven、eclipse 和 WebSphere Application Server liberty v16.0.0.4 不知道我做错了什么,这里是相关文件:

Controller.java:

package ManagedBeans;

import java.io.PrintWriter;
import java.io.Serializable;
import java.io.StringWriter;

import javax.enterprise.context.SessionScoped;
import javax.inject.Named;
import javax.servlet.http.Part;

import Main.FileHandler;
import Main.IBMEmployee;

@Named("controller")
@SessionScoped
public class Controller implements Serializable 

    private Part telstraCustomersFile;
    private Part terminateesFile;
    private String telstraPass;
    private String termineesPass;
    private String exception;
    private String exceptionTrace;
    private FileHandler fileHandler = new FileHandler();
    private IBMEmployee[] potentialMatches;

    public String perform()
    
        try 
            fileHandler.process(telstraCustomersFile, terminateesFile, telstraPass, termineesPass);
            potentialMatches = fileHandler.potentialMatches;
        
        catch (Exception ex) 
            StringWriter errors = new StringWriter();
            ex.printStackTrace(new PrintWriter(errors));
            exception = ex.toString();
            exceptionTrace = errors.toString();

            return ("errorPage.xhtml");
        

        return ("searchExcel.xhtml");
    

    public void setTelstraPass(String value)  telstraPass = value; 
    public String getTelstraPass()  return telstraPass; 
    public void setTermineesPass(String value)  termineesPass = value; 
    public String getTermineesPass()  return termineesPass; 
    public void setTelstraCustomersFile(Part file)  telstraCustomersFile = file; 
    public Part getTelstraCustomersFile()  return telstraCustomersFile; 
    public void setTerminateesFile(Part file)  terminateesFile = file; 
    public Part getTerminateesFile()  return terminateesFile; 
    public String getException()  return exception; 
    public String getExceptionTrace()  return exceptionTrace; 
    public IBMEmployee[] getExactMatches()  return fileHandler.exactMatches; 
    public IBMEmployee[] getPotentialMatches()  return potentialMatches; 

index.xhtml:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core">   
      <h:head>
        <title>Termination Checklist</title>
        <h:outputScript name="js/scripts.js"/>      
        <h:outputStylesheet name="css/PageFormat.css"/>

        Created By Jerry Boyaji
        <h:graphicImage id="IBMLogo" name="images/IBM-logo.jpg"   />
    </h:head>
    <h:body onload="enableDisableSubmitBtn()">
        <div id="ContentFrame">
            <h1>Corporate Account Termination Application (CATA)</h1>
            <h3>Excel Search: <br/> Select your spreadsheet files to upload:</h3>
            <br/>
            <br/>
            <h:form id="excelInputForm" enctype="multipart/form-data" 
                name="UploadForm" 
                method="Post">

                Telstra Spreadsheet File: 

                <br/>
                <h:inputFile
                    id="telstraCustomers" 
                    name="telstra file" 
                    size="40" 
                    value="#controller.telstraCustomersFile"
                    required="True"
                    onchange="enableDisableSubmitBtn()"/>

                Password if Applicable: 
                <h:inputSecret
                    id="telstraSpreadsheetPassword"
                    value="#controller.telstraPass"
                    label="Password if Applicable"/>

                <br/>
                <br/>

                Termination Spreadsheet File: 
                <br/>           
                <h:inputFile
                    id="terminatees" 
                    name="termination file" 
                    size="40"
                    value="#controller.terminateesFile"
                    required="True"
                    onchange="enableDisableSubmitBtn()" />

                Password if Applicable: 
                <h:inputSecret
                    id="termineesSpreadsheetPassword"
                    value="#controller.termineesPass"
                    label="Password if Applicable"/>    

                <br/>
                <br/>

                <h:commandButton 
                    id="submit"
                    value="Upload and Continue" 
                    type = "submit"
                    action="#controller.perform"/>

            </h:form>
        </div>
    </h:body>
</html>

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">
    <display-name>MainApplication</display-name>
    <welcome-file-list>
        <welcome-file>index.xhtml</welcome-file>
    </welcome-file-list>
    <context-param>
        <description>
        State saving method: 'client' or 'server' (=default). See JSF Specification 2.5.2</description>
        <param-name>javax.faces.STATE_SAVING_METHOD</param-name>
        <param-value>client</param-value>
    </context-param>
    <context-param>
        <param-name>javax.servlet.jsp.jstl.fmt.localizationContext</param-name>
        <param-value>resources.application</param-value>
    </context-param>
    <servlet>
        <servlet-name>Faces Servlet</servlet-name>
        <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>Faces Servlet</servlet-name>
        <url-pattern>*.xhtml</url-pattern>
    </servlet-mapping>

    <security-constraint>
        <display-name>HTTPS Redirect Security Constraint</display-name>
        <web-resource-collection>
            <web-resource-name>MainApplication</web-resource-name>
            <url-pattern>/*</url-pattern>
        </web-resource-collection>
        <user-data-constraint>
            <transport-guarantee>CONFIDENTIAL</transport-guarantee>
        </user-data-constraint>
    </security-constraint>
</web-app>

Server.xml:

<server description="jerry's local server">

    <!-- Enable features -->
    <featureManager>
        <feature>localConnector-1.0</feature>
        <feature>websocket-1.1</feature>
        <feature>appSecurity-2.0</feature>
        <feature>cdi-1.2<feature>
        <feature>jsp-2.3</feature>
    </featureManager>

    <basicRegistry id="basic">
      <user name="admin" password="****"/>
   </basicRegistry>

   <administrator-role>
      <user>admin</user>
   </administrator-role>

    <remoteFileAccess>
        <writeDir>$server.config.dir</writeDir>
    </remoteFileAccess>

    <!-- To access this server from a remote client add a host attribute to the following element, e.g. host="*" -->
    <httpEndpoint host="localhost" httpPort="9080" httpsPort="9443" id="defaultHttpEndpoint"/>

    <!-- Automatically expand WAR files and EAR files -->
    <applicationManager autoExpand="true"/>

    <applicationMonitor updateTrigger="mbean"/>
    <keyStore id="defaultKeyStore" password="****"/>

    <webApplication id="MainApplication" location="MainApplication.war" name="MainApplication"/>
</server>

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/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>Termination-Checklist-Maven</groupId>
  <artifactId>MainApplication</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>war</packaging>

  <name>MainApplication</name>
  <url>http://maven.apache.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <pluginRepositories>
        <!-- Configure WASdev repository -->
        <pluginRepository>
            <id>WASdev</id>
            <name>WASdev Repository</name>
            <url>http://public.dhe.ibm.com/ibmdl/export/pub/software/websphere/wasdev/maven/repository/</url>
            <layout>default</layout>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
            <releases>
                <enabled>true</enabled>
            </releases>
        </pluginRepository>
    </pluginRepositories>

  <build>
    <plugins>
      <plugin>
        <artifactId>maven-war-plugin</artifactId>
        <version>3.0.0</version>
        <configuration>
          <webXml>WebContent/WEB-INF/web.xml</webXml>
        </configuration>
      </plugin>
      <plugin>
            <groupId>com.ibm.websphere.wlp.maven.plugins</groupId>
            <artifactId>liberty-maven-plugin</artifactId> 
            <version>1.0</version>
            <configuration>
                <serverHome>/Applications/WebProfile</serverHome>
            </configuration>
      </plugin>
    </plugins>
  </build>

  <repositories>
    <!--other repositories if any-->
    <repository>
        <id>project.local</id>
        <name>project</name>
        <url>file:$project.basedir/repo</url>
    </repository>
  </repositories>


  <dependencies>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>3.8.1</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.glassfish</groupId>
        <artifactId>javax.faces</artifactId>
        <version>2.3.0</version>
    </dependency>
    <dependency>
        <groupId>javax.enterprise</groupId>
        <artifactId>cdi-api</artifactId>
        <version>1.2</version>
        <scope>provided<scope>
    </dependency>
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi</artifactId>
        <version>3.16-beta2</version>
    </dependency>
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi-ooxml</artifactId>
        <version>3.16-beta2</version>
    </dependency>
    <dependency>
        <groupId>org.glassfish</groupId>
        <artifactId>javax.json</artifactId>
        <version>1.0.4</version>
    </dependency>
    <dependency>
        <groupId>javax.json</groupId>
        <artifactId>javax.json-api</artifactId>
        <version>1.0</version>
    </dependency>
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi-ooxml-schemas</artifactId>
        <version>3.16-beta2</version>
    </dependency>
        <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>3.1.0</version>
    </dependency>
  </dependencies>
</project>

faces-config.xml:

<?xml version='1.0' encoding='UTF-8'?>
<faces-config version="2.3"
    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-facesconfig_2_3.xsd"> 
</faces-config>

我的 WEB-INF 文件夹中还有一个空 beans.xml 文件,其中包含我的 web.xml 和 faces-config.xml。

据我所知,我所做的一切都是正确的,我没有 JSF 或 CDI 的竞争实现,并且没有使用 JSF 包中的任何范围。我完全不知道为什么这不起作用...

【问题讨论】:

尝试添加jsf-2.2功能,因为我只看到jsp-2.3 我使用的是 jsf-2.3,它与我的 .war 一起打包,正如您在我的 pom.xml 中看到的那样,为什么要添加到以前的版本中来解决这个问题? Jsp-2.3 也是必需的,因为没有它就无法工作(我认为是因为 jsf-2.3 或 cdi-1.2 需要它作为提供的依赖项,不记得它是哪个) 您的应用程序很简单,可以使用内置的 jsf-2.2 运行,这是 Java EE 7 的默认设置,所以为了测试,您应该尝试从您的战争中删除任何外部 jsf 库,并且使用服务器提供的运行。 升级到 jsf-2.3 以利用异步性和 ,恢复到 jsf-2.3(作为外部库)@ManagedBean 注释,就像我以前使用的一样,仍然可以使用 jsf -2.2 默认功能 啊,是的,这就是问题所在。仅提供的 jsf 实现适用于 CDI 注释。检查这些页面 - CDI integration with JavaServer Faces 和 Using a Custom JSF implementation(Mojarra) with WebSphere Liberty Profile and WAS full Profile。因此,您要么使用提供的 CDI,要么使用自定义的 JSF bean。 【参考方案1】:

正如 Gas 指出的那样,问题在于 WAS 中的内置 CDI 功能不适用于外部 JSF 库。

请参阅 IBM 支持页面上的 my post 以确认这一点。

使用 JSF-2.2 仍然使用 Web 套接字的一种方法是使用 @Gas 指出的 Javax.websocket 包。但是,此 Web 套接字实现的局限性在于,将 SessionScoped ManagedBean 中包含的数据发送到该会话的客户端并不像我希望的那样使用来自 JSF-2.3 的 f:websocket做。

【讨论】:

以上是关于JSF-2.3 找不到我的 @Named CDI-1.2 托管 bean的主要内容,如果未能解决你的问题,请参考以下文章

Wildfly 以错误开头。 javax.faces.FacesException:找不到 CDI BeanManager

CDI @Named bean 中的 @javax.faces.bean.ManagedProperty 返回 null

找不到 CDI BeanManager

@PostConstruct 中的 CDI 参数

在 WEB-INF/lib 内的 JAR 中找不到 CDI 实例

由于 CDI/Weld 中的 @Named,@ManagedBeans 在 JavaEE6 中过时了吗?