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

问题描述:

我正在创建我的第一个项目Java EE 7,但是遇到了麻烦.感谢任何帮助.

I'm creating my first project Java EE 7, but I'm having trouble. Appreciate any help.

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

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

When the application start, the Tomcat log shows the following message:

"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的按钮时,出现错误:

when I click on the button that calls the managed bean, I get the error:

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>

这些主题对我没有帮助:

These topics have not helped me:

  • Java EE 6 @javax.annotation.ManagedBean vs. @javax.inject.Named vs. @javax.faces.ManagedBean
  • Target Unreachable identifier resolved to null
  • Target Unreachable, identifier resolved to null
  • javax.el.PropertyNotFoundException : Target Unreachable, identifier 'login' resolved to null Spring + JSF
  • http://www.andrejkoelewijn.com/blog/2010/03/05/jee-cdi-tip-target-unreachable-identifier-resolved-to-null/

Tomcat作为准系统JSP/Servlet容器不支持CDI.您如何确切地安装CDI?您是否真的只是为了将代码编译而将javaee-api.jar放在了/WEB-INF/lib中?哦,请不要,这不是正确的方法. Java EE API JAR仅包含API类,而不包含具体实现.摆脱整个JAR.它可能会导致许多其他可移植性问题,例如此答案中所述的问题:

Tomcat as being a barebones JSP/Servlet container doesn't support CDI out the box. How exactly did you install CDI? Did you really drop javaee-api.jar in /WEB-INF/lib just to get your code to compile? Oh please no, this is not the right way. The Java EE API JAR contains solely the API classes, not the concrete implementation. Get rid of the whole JAR. It can cause many other portability troubles like as the ones described in this answer: How do I import the javax.servlet API in my Eclipse project? You should actually be installing the concrete implementation along with the specific API.

您有2个选择:

  1. 拖放Tomcat并使用真正的Java EE容器.使用Tomcat时,只需进入 TomEE .非常简单,下载TomEE Web配置文件zip文件,将其解压缩并完全集成到Eclipse中与对Tomcat一样.不要忘记从webapp中删除Java EE JAR文件,并将项目属性中的 Targeted Runtime 属性从Tomcat更改为TomEE,以便正确解决Java EE依赖项.

  1. Drop Tomcat and go for a true Java 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 Java EE JAR file from webapp and alter the Targeted Runtime property in project's properties from Tomcat to TomEE so that Java EE dependencies are properly resolved.

不需要其他JAR或配置.您甚至可以从Web应用程序中删除JSF JAR.作为真正的Java EE容器,TomEE已经提供了现成的JSF和CDI.如果您使用的是Maven,则下面的坐标就足够了.

No additional JARs or configuration is necessary. You can even remove the JSF JARs from your webapp. TomEE as being a true Java EE container already provides among others JSF and CDI out the box. In case you're using Maven, the below coordinate is sufficient.

<dependency>
    <groupId>javax</groupId>
    <artifactId>javaee-web-api</artifactId>
    <version><!-- 8.0 or 7.0 or 6.0 --></version>
    <scope>provided</scope>
</dependency>

请注意provided的重要性及其含义,例如目标运行时已提供了此功能".另请参见如何通过Maven正确安装和配置JSF库?.

Note the importance of provided and its meaning as in "the target runtime already provides this out the box". See also How to properly install and configure JSF libraries via Maven?.

在Tomcat上安装真正的CDI实现. Weld 是可用的CDI实现之一.在焊接安装指南中,您可以找到说明如何将其集成到Tomcat中.为了完整性和将来的参考,以下是这些步骤:

Install a true CDI implementation on Tomcat. 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. 拖放 weld-servlet-shaded.jar 在Webapp的/WEB-INF/lib中.如果您使用的是Maven,请使用此坐标:

  1. Drop the weld-servlet-shaded.jar 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>3.0.5.Final</version>
</dependency>

  • 在Web应用程序中创建具有以下内容的/META-INF/context.xml文件:

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

    请注意,当您使用Mojarra 2.2.11或更高版本时,此步骤并非绝对必要,因为在JNDI中不存在时,它可以通过ServletContext找到它.

    Note that this step is not strictly necessary when you're using Mojarra 2.2.11 or newer as it will be able to find it via ServletContext when absent in JNDI.

    在Web应用程序中创建一个空的/WEB-INF/beans.xml文件.

    Create an empty /WEB-INF/beans.xml file in webapp.

    就这样(注意:在较旧的Weld Servlet版本中,您也需要在web.xml中显式注册CDI bean管理器和Weld侦听器,但这对于当前版本是不必要的.)

    That's it (note: in older Weld Servlet versions, you'd need to explicitly register the CDI bean manager and Weld listener in web.xml too, but that's unnecessary with current versions).

    如果您更喜欢Weld之上的OpenWebBeans作为CDI实现,请转到此博客以获取详细的Maven安装说明:

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


    无关与具体问题无关,Tomcat 7的JSP/Servlet API确实不符合Java EE 7的那些API,而是符合Java EE 6(Servlet 3.0 /JSP 2.2).如果要使用与Java EE 7(Servlet 3.1/JSP 2.3)等效的Tomcat,则应查看Tomcat8.另请参见 Apache Tomcat版本矩阵.


    Unrelated to the concrete problem, the JSP/Servlet APIs of Tomcat 7 do not comply those APIs of Java EE 7, instead it complies Java EE 6 (Servlet 3.0 / JSP 2.2). If you want the Tomcat equivalent of Java EE 7 (Servlet 3.1 / JSP 2.3), then you should be looking at Tomcat 8. See also Apache Tomcat version matrix.