Question

I am working in a Java EE maven project and I'm experiencing problems with dependency injection when attempting to deploy to a Glassfish4 server.

The maven project is structured in three separate modules under a top level pom like so:

kronos:

  • ear
  • ejb
  • web

Kronos is the parent module, web handles the front-end code (JSF, ManagedBeans), ejb has the back-end code (EJBs, JPA) and ear handles the ear artefact generation and deployment. The actual pom.xml files are listed at the end of this post.

Inside the ejb module we have a StaffDAO interface and a StaffDAOImpl stateless bean (annotated @javax.ejb.Stateless). At the moment this is the only EJB bean in the code and it is certainly the only bean implementing StaffDAO.

When attempting to inject the bean inside a ManagedBean (@ManagedBean, @RequestScoped) in the web component using the @Inject annotation on a field of type StaffDAO we get the following error when attempting to deploy to Glassfish:

    [glassfish 4.0] [SEVERE] [] [javax.enterprise.system.core] [tid: _ThreadID=35 _ThreadName=admin-listener(4)] [timeMillis: 1393775922183] [levelValue: 1000] [[
      Exception while loading the app : CDI deployment failure:WELD-001409 Ambiguous dependencies for type [StaffDAO] with qualifiers [@Default] at injection point [[BackedAnnotatedField] @Inject private managedbeans.DummyUserBean.staffDAO]. Possible dependencies [[Session bean [class persistence.dao.impl.StaffDAOImpl with qualifiers [@Any @Default]; local interfaces are [StaffDAO], Session bean [class persistence.dao.impl.StaffDAOImpl with qualifiers [@Any @Default]; local interfaces are [StaffDAO]]]
    org.jboss.weld.exceptions.DeploymentException: WELD-001409 Ambiguous dependencies for type [StaffDAO] with qualifiers [@Default] at injection point [[BackedAnnotatedField] @Inject private managedbeans.DummyUserBean.staffDAO]. Possible dependencies [[Session bean [class persistence.dao.impl.StaffDAOImpl with qualifiers [@Any @Default]; local interfaces are [StaffDAO], Session bean [class persistence.dao.impl.StaffDAOImpl with qualifiers [@Any @Default]; local interfaces are [StaffDAO]]]

Using the @EJB annotation instead gives us:

[glassfish 4.0] [SEVERE] [NCLS-CORE-00026] [javax.enterprise.system.core] [tid: _ThreadID=34 _ThreadName=admin-listener(3)] [timeMillis: 1393776686187] [levelValue: 1000] [[
  Exception during lifecycle processing
java.lang.IllegalArgumentException: Cannot resolve reference [Remote ejb-ref name=managedbeans.DummyUserBean/staffDAO,Remote 3.x interface =persistence.dao.StaffDAO,ejb-link=null,lookup=,mappedName=,jndi-name=,refType=Session] because there are [2] ejbs in the application with interface persistence.dao.StaffDAO. 
Some of the possible causes: 
1. The EJB bean class was packaged in an ear lib library (or through any other library mechanism which makes the library visible to all component modules), this makes all the component modules include this bean class indirectly. 
2. The EJB bean class was packaged in a component module which references the EJB, either directly or indirectly through Manifest, WEB-INF/lib. 
The EJB bean class should only be packaged in the declaring ejb module and not the referencing modules. The referencing modules should only include EJB interfaces.

I believe, though I am not sure, that this is caused by a mistake in our artefact generation that results in the StaffDAOImpl EJB being packaged twice, but I am not sufficiently familiar with maven to confirm and fix that. Any help would be appreciated.

Code:

StaffDAO:

public interface StaffDAO {...}

StaffDAOImpl:

import javax.ejb.Stateless;

@Stateless
public class StaffDAOImpl implements persistence.dao.StaffDAO {...}

DummyUserBean:

import javax.faces.bean.ManagedBean;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;

@ManagedBean(name = "dummyUserBean")
@RequestScoped
public class DummyUserBean {

    @Inject
    private StaffDAO staffDAO;

    ...
}

The pom.xml files are:

kronos:

<?xml version="1.0" encoding="UTF-8"?>
<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>kronos</groupId>
    <artifactId>kronos</artifactId>
    <packaging>pom</packaging>
    <version>1.0-SNAPSHOT</version>
    <modules>
        <module>ejb</module>
        <module>web</module>
        <module>ear</module>
    </modules>

    <dependencies>
        <dependency>
            <groupId>javax</groupId>
            <artifactId>javaee-api</artifactId>
            <version>7.0</version>
        </dependency>
    </dependencies>

    <properties>
        <maven.compiler.source>1.7</maven.compiler.source>
        <maven.compiler.target>1.7</maven.compiler.target>
    </properties>

    <build>
        <finalName>HelloGlassfish4</finalName>
    </build>
</project>

ear:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://maven.apache.org/POM/4.0.0"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>kronos</artifactId>
        <groupId>kronos</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>ear</artifactId>
    <packaging>ear</packaging>

    <dependencies>
        <dependency>
            <groupId>kronos</groupId>
            <artifactId>ejb</artifactId>
            <version>1.0-SNAPSHOT</version>
            <type>ejb</type>
        </dependency>

        <dependency>
            <groupId>kronos</groupId>
            <artifactId>web</artifactId>
            <version>1.0-SNAPSHOT</version>
            <type>war</type>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.glassfish.maven.plugin</groupId>
                <artifactId>maven-glassfish-plugin</artifactId>
                <version>2.1</version>
                <configuration>
                    <glassfishDirectory>${local.glassfish.home}</glassfishDirectory>
                    <user>${local.glassfish.user}</user>
                    <passwordFile>${local.glassfish.passfile}</passwordFile>
                    <domain>
                        <name>${local.glassfish.domain}</name>
                        <adminPort>${local.glassfish.adminPort}</adminPort>
                        <httpPort>${local.glassfish.httpPort}</httpPort>
                    </domain>
                    <components>
                        <component>
                            <name>${project.artifactId}</name>
                            <artifact>target/${project.build.finalName}.ear</artifact>
                        </component>
                    </components>
                    <debug>true</debug>
                    <terse>false</terse>
                    <echo>true</echo>
                </configuration>
            </plugin>

            <plugin>
                <artifactId>maven-ear-plugin</artifactId>
                <version>2.8</version>
                <configuration>
                    <modules>
                        <webModule>
                            <groupId>kronos</groupId>
                            <artifactId>web</artifactId>
                        </webModule>
                        <ejbModule>
                            <groupId>kronos</groupId>
                            <artifactId>ejb</artifactId>
                        </ejbModule>
                    </modules>
                    <defaultLibBundleDir>lib</defaultLibBundleDir>
                </configuration>
            </plugin>
        </plugins>
        <finalName>kronos</finalName>
    </build>
</project>

ejb:

<?xml version="1.0" encoding="UTF-8"?>
<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">
    <parent>
        <artifactId>kronos</artifactId>
        <groupId>kronos</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>ejb</artifactId>

    <dependencies>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
            <version>3.6.7.Final</version>
        </dependency>

        <dependency>
            <groupId>org.postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <version>9.2-1003-jdbc4</version>
        </dependency>

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.6</version>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
        </dependency>

        <dependency>
            <groupId>org.mockito</groupId>
            <artifactId>mockito-all</artifactId>
            <version>1.9.5</version>
        </dependency>

        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>16.0.1</version>
        </dependency>

        <dependency>
            <groupId>javax.validation</groupId>
            <artifactId>validation-api</artifactId>
            <version>1.0.0.GA</version>
        </dependency>

        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>4.1.0.Final</version>
        </dependency>

        <dependency>
            <groupId>joda-time</groupId>
            <artifactId>joda-time</artifactId>
            <version>2.3</version>
        </dependency>


    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.16</version>
                <configuration>
                    <skipTests>true</skipTests>
                </configuration>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-ejb-plugin</artifactId>
                <version>2.3</version>
                <configuration>
                    <ejbVersion>3.2</ejbVersion>
                    <archive>
                        <manifest>
                            <addClasspath>true</addClasspath>
                        </manifest>
                    </archive>
                </configuration>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.1</version>
                <configuration>
                    <source>1.7</source>
                    <target>1.7</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

web:

<?xml version="1.0" encoding="UTF-8"?>
<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">
    <parent>
        <artifactId>kronos</artifactId>
        <groupId>kronos</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>web</artifactId>
    <packaging>war</packaging>

    <dependencies>
        <dependency>
            <groupId>kronos</groupId>
            <artifactId>ejb</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

        <dependency>
            <groupId>org.primefaces</groupId>
            <artifactId>primefaces</artifactId>
            <version>4.0</version>
            <type>jar</type>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <configuration>
                    <webXml>src\main\webapp\WEB-INF\web.xml</webXml>
                </configuration>
            </plugin>
        </plugins>
        <finalName>web</finalName>
    </build>
</project>
Was it helpful?

Solution

It turns out my original suspicion was correct. Because the web module depended on the ejb module the ejb classes were added to the war archive. Because of that when the ear was built from the war and the ejb jar those classes ended up being packaged twice and that confused CDI.

I fixed it by making a fourth maven module to hold the code that is needed by both the ejb and web modules, adding it as a dependency to those two and breaking the web's dependency on the ejb. Now it works fine.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top