How to install and use CDI on Tomcat?
Asked Answered
C

2

39

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

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"

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:

Caucasian answered 25/9, 2013 at 3:58 Comment(3)
Show your faces-config.xml fileShod
Thank's @Kalathoki, file added. Almost nothing, because I'm using annotations.Lorin
make sure indexMB bean is constructed successfully.Ermin
H
82

Tomcat as being a barebones JSP/Servlet container doesn't support CDI out the box. It is not correct to drop jakartaee-api.jar or javaee-api.jar in /WEB-INF/lib just to get your code to compile. The JEE 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 / jakarta.servlet API in my Eclipse project? You should actually be installing the concrete implementation along with the specific API.

You have 2 options:

  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?

Hyperploid answered 25/9, 2013 at 11:31 Comment(8)
As I said, "it's my first Java EE 7 project". Thank you very much.Lorin
I switched to TomEE, but to initialize it shows the following error: com.sun.faces.config.ConfigurationException: Factory 'javax.faces.application.ApplicationFactory' was not configured properly. I saw the topic could not find Factory: javax.faces.context.FacesContextFactory, but it didn't help. Any comments?Lorin
I switched to Glassfish 4 and I got the same initial error (Target Unreachable, identifier 'indexMB' resolved to null). I removed javaee-api-7.0.jar . Comments?Lorin
As to TomEE, it already bundles JSF (MyFaces). If you still bundle another JSF impl in your webapp, then you get exactly this exception. Just remove JSF JARs from your webapp. As to GlassFish 4, not sure on that, but it's likely also caused by a dirty classpath.Hyperploid
Proceeding. ... The startup errors on TomEE stopped, but now the JSF does not load (though not display no error on log). GlassFish maintains the initial error. The only libs loaded are: primefaces-3.5.jar, commons-io.jar, commons-fileupload.jarLorin
Looking best, the startup errors on TomEE console stopped, but TomEE log shows Exception sending context initialized event to listener instance of class com.sun.faces.config.ConfigureListener java.lang.NoClassDefFoundError: com/sun/faces/config/configprovider/MetaInfFaceletTaglibraryConfigProvider, and JSF does not load.Lorin
Even so, for CDI 1.2 and JSF 2.2, we only need Servlet 3.0. I did not try, but that should mean that we can deploy those on Tomcat 7.Decamp
For me this was not enough. I'm not using CDI at all, but rather Spring, but I want OmniFaces 2+. I'm getting javax.naming.NamingException: WELD-001300: Unable to locate BeanManager. So additionally to the above instructions I had to introduce at least 1 stub CDI bean annotated with @javax.inject.Named to be located under /WEB-INF/classes to get it fixed.Niccolite
D
0

Other possible option is leaving beans.xml in your deployment.

Daguerre answered 3/6, 2014 at 12:27 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.