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

39

我正在创建我的第一个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>

以下主题并没有帮助我:


1
展示你的 faces-config.xml 文件。 - Yubaraj
谢谢@Kalathoki,文件已添加。使用注释的原因是几乎没有其他东西需要添加。 - Rogério Arantes
确保 indexMB bean 构建成功。 - erencan
2个回答

81
作为一个基础的JSP/Servlet容器,Tomcat不支持CDI。将jakartaee-api.jarjavaee-api.jar放入/WEB-INF/lib目录下并不能正确编译代码。JEE API JAR仅包含API类,而不包含具体的实现。删除整个JAR文件。它可能会导致其他可移植性问题,如本答案中所描述的问题:我该如何在Eclipse项目中导入javax.servlet/jakarta.servlet API? 实际上,您应该安装具体的实现以及特定的API,有两种选择:
  1. Drop Tomcat and go for a true Jakarta EE container. As you're using Tomcat, just step over to TomEE. It's really simple, download the TomEE web profile zip file, extract it and integrate it in Eclipse exactly the same way as you did for Tomcat. Don't forget to remove the Jakarta EE JAR file from webapp and alter the Targeted Runtime property in project's properties from Tomcat to TomEE so that Jakarta EE dependencies are properly resolved. See also What exactly is Java EE?

    No additional JARs or configuration is necessary. You can even remove the manually installed JSF/JSTL/CDI/BV/JPA/EJB/JTA/JSONPJAX-RS/etc/etc libraries from your webapp. TomEE as being a true Jakarta EE container already provides them all out the box. In case you're using Maven, the below coordinate is sufficient.

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

    Note the importance of provided and its meaning as in "the target runtime already provides this out the box". See also How to properly configure Jakarta EE libraries in Maven pom.xml for Tomcat? for detailed pom.xml examples of Tomcat and normal JEE containers.


  2. If you want to stick to Tomcat, then you need to manually install a true CDI implementation via the webapp. Below instructions assume Tomcat 10+. Weld is one of the available CDI implementations. In the Weld installation guide you can find instructions how to integrate it in Tomcat. For sake of completeness and future reference, here are the steps:

    1. For Tomcat 10.1.x, drop the weld-servlet-shaded.jar of version 5.x in webapp's /WEB-INF/lib. In case you're using Maven, use this coordinate:

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

      For Tomcat 10.x, use weld-servlet-shaded.jar of version 4.x instead:

       <dependency>
           <groupId>org.jboss.weld.servlet</groupId>
           <artifactId>weld-servlet-shaded</artifactId>
           <version>4.0.3.Final</version>
       </dependency>
      
    2. Optionally, create a /META-INF/context.xml file in webapp with following content:

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

      This step is is only necessary when the CDI-dependent library tries to manually find it in JNDI. This step is not necessary when you're using for example Jakarta Faces / JSF version 2.3 or newer.

    3. Create a /WEB-INF/beans.xml file in webapp to trigger activation of CDI. It can be kept empty.

    That's it.

    In case you prefer OpenWebBeans above Weld as CDI implementation, or need to install CDI in Tomcat 9.x or older, head to this blog for detailed Maven installation instructions: How to install CDI in Tomcat?


就像我说的那样,“这是我的第一个Java EE 7项目”。非常感谢。 - Rogério Arantes
我切换到了TomEE,但是在初始化时出现了以下错误:com.sun.faces.config.ConfigurationException: Factory 'javax.faces.application.ApplicationFactory' was not configured properly. 我看到了这个主题could not find Factory: javax.faces.context.FacesContextFactory,但它没有帮助。有任何评论吗? - Rogério Arantes
我切换到Glassfish 4后,遇到了相同的初始错误(“Target Unreachable,标识符'indexMB'解析为null”)。我删除了javaee-api-7.0.jar。有什么建议吗? - Rogério Arantes
2
关于TomEE,它已经捆绑了JSF(MyFaces)。如果您仍然在Web应用程序中捆绑另一个JSF实现,则会出现此异常。只需从Web应用程序中删除JSF JAR文件即可。至于GlassFish 4,不确定,但很可能也是由于脏类路径引起的。 - BalusC
进行中。... TomEE上的启动错误已经停止,但现在JSF无法加载(尽管日志上没有显示任何错误)。GlassFish仍然保留最初的错误。加载的唯一库是:primefaces-3.5.jar、commons-io.jar和commons-fileupload.jar。 - Rogério Arantes
显示剩余3条评论

0

另一个可能的选择是将beans.xml保留在您的部署中。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接