jsf - 如何在Tomcat上安装和使用CDI?

标签 jsf tomcat cdi jsf-2.2

我正在创建我的第一个项目 Java EE 7,但遇到了问题。感谢任何帮助。

  • Tomcat 7.0.34
  • JSF 2.2
  • Primefaces 3.5
  • javaee-api-7.0.jar

当应用程序启动时,Tomcat 日志显示以下消息:

"validateJarFile (C:\...\build\web\WEB-INF\lib\javaee-api-7.0.jar)-jar not loaded. See Servlet 2.3 Spec, section 9.7.2. Offending class: javax/servlet/Servlet .class"

当我点击调用托管 bean 的按钮时,出现错误:

Advertência: /index.xhtml @18,66 value="#{indexMB.user}": Target Unreachable, identifier 'indexMB' resolved to null
javax.el.PropertyNotFoundException: /index.xhtml @18,66 value="#{indexMB.user}": Target Unreachable, identifier 'indexMB' resolved to null

IndexMB

@Named("indexMB")
@RequestScoped
public class IndexMB {

private String password;
private String user;

public String loginTest(){
    return (this.user.equals("admin") ? "adminPage" : "inOutPage");
}

// getters and setters
}

index.xhtml

<html ...>

<f:loadBundle basename="i18n" var="bundle" />
<h:head>
    <title>#{bundle['index_title']}</title>
</h:head>
<h:body>
    #{bundle['index_appname']}
    <br />
    <h:form id="frmIndex">
        <p:panelGrid columns="2">
            <p:outputLabel for="user" value="#{bundle['lblUser']}" />
            <p:inputText id="user" value="#{indexMB.user}" />

            <p:outputLabel for="password" value="#{bundle['lblPassword']}" />
            <p:password id="password" value="#{indexMB.password}" />
        </p:panelGrid>
        <p:commandButton action="#{indexMB.loginTest}" value="#{bundle['btn_login']}" />
    </h:form> 
</h:body>

faces-config.xml

<?xml version='1.0' encoding='UTF-8'?>
<faces-config version="2.2"
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">

<application>
    <locale-config>
        <default-locale>pt_BR</default-locale>
        <supported-locale>en</supported-locale>
        <supported-locale>fr</supported-locale>
    </locale-config>
</application>

这些主题对我没有帮助:

最佳答案

作为准系统 JSP/Servlet 容器的 Tomcat 不支持开箱即用的 CDI。将 jakartaee-api.jarjavaee-api.jar 放入 /WEB-INF/lib 只是为了获取代码是不正确的编译。 JEE API JAR 仅包含 API 类,不包含具体实现。摆脱整个 JAR。它可能会导致许多其他可移植性问题,例如此答案中描述的问题:How do I import the javax.servlet / jakarta.servlet API in my Eclipse project?您实际上应该安装具体的实现以及特定的 API。

你有两个选择:

  1. 放弃 Tomcat,转而使用真正的 Jakarta EE 容器。当您使用 Tomcat 时,只需转到 TomEE .真的很简单,download the TomEE web profile zip file ,提取它并将其集成到 Eclipse 中,就像您对 Tomcat 所做的那样。不要忘记从 webapp 中删除 Jakarta EE JAR 文件,并将项目属性中的 Targeted Runtime 属性从 Tomcat 更改为 TomEE,以便正确解析 Jakarta EE 依赖项。另见 What exactly is Java EE?

    不需要额外的 JAR 或配置。您甚至可以从 Web 应用程序中删除手动安装的 JSF/JSTL/CDI/BV/JPA/EJB/JTA/JSONPJAX-RS/etc/etc 库。 TomEE 作为一个真正的 Jakarta EE 容器已经提供了所有开箱即用的功能。如果您使用的是 Maven,则以下坐标就足够了。

     <dependency>
         <groupId>jakarta.platform</groupId>
         <artifactId>jakarta.jakartaee-web-api</artifactId>
         <version><!-- e.g. 10.0.0 or 9.1.0 --></version>
         <scope>provided</scope>
     </dependency>
    

    请注意 provided 的重要性及其在“目标运行时已经开箱即用”中的含义。另见 How to properly configure Jakarta EE libraries in Maven pom.xml for Tomcat?有关 Tomcat 和普通 JEE 容器的详细 pom.xml 示例。


  2. 如果您想坚持使用 Tomcat,则需要通过 webapp 手动安装真正的 CDI 实现。以下说明假定 Tomcat 10+。 Weld是可用的 CDI 实现之一。在 the Weld installation guide您可以找到如何将其集成到 Tomcat 中的说明。为了完整性和 future 引用,以下是步骤:

    1. 对于 Tomcat 10.1.x,删除 weld-servlet-shaded.jar of version 5.x在 webapp 的 /WEB-INF/lib 中。如果您使用的是 Maven,请使用此坐标:

       <dependency>
           <groupId>org.jboss.weld.servlet</groupId>
           <artifactId>weld-servlet-shaded</artifactId>
           <version>5.1.0.Final</version>
       </dependency>
      

      对于 Tomcat 10.x,使用 weld-servlet-shaded.jar of version 4.x相反:

       <dependency>
           <groupId>org.jboss.weld.servlet</groupId>
           <artifactId>weld-servlet-shaded</artifactId>
           <version>4.0.3.Final</version>
       </dependency>
      
    2. 可选地,在 webapp 中创建一个包含以下内容的 /META-INF/context.xml 文件:

       <Context>
           <Resource name="BeanManager" 
               auth="Container"
               type="jakarta.enterprise.inject.spi.BeanManager"
               factory="org.jboss.weld.resources.ManagerObjectFactory"/>
       </Context>
      

      仅当依赖于 CDI 的库尝试在 JNDI 中手动查找时才需要执行此步骤。当您使用例如 Jakarta Faces/JSF 2.3 或更新版本时,此步骤不是必需的。

    3. 在 webapp 中创建一个 /WEB-INF/beans.xml 文件来触发 CDI 的激活。它可以保持为空。

    就是这样。

    如果您更喜欢 OpenWebBeans 而不是 Weld 作为 CDI 实现,或者需要在 Tomcat 9.x 或更早版本中安装 CDI,请访问此博客以获取详细的 Maven 安装说明:How to install CDI in Tomcat?

关于jsf - 如何在Tomcat上安装和使用CDI?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24922739/

相关文章:

java - Tomcat 无法识别我的上下文

java - Could not create the Java virtual machine 报错?

jakarta-ee - 如何将 CDI 依赖项注入(inject) JAX-RS ClientRequestFilter 提供程序

ajax - 重定向到 JSF ajax 错误页面的模式

java - 使用带有 PrimeFaces 的 JSF 单击菜单后 CSS 丢失

tomcat - 无法在 Netbeans 7.1 中添加外部服务器 Tomcat

servlets - 在 Servlet 中注入(inject) CDI session Bean

java - 焊接和 Java SE

html - 什么时候应该使用 JSF 组件,什么时候应该使用 html 标签?

ajax - 通过ajax禁用验证器