Java EE 7 CDI - Injection doesn't work, sendin

2019-04-10 12:07发布

问题:

I have a problem with my injection, it's the first time I try it. I'm working with Wildfly and Java EE 7. I've got a NullPointerException when trying to access Authenticator instance in LoginController.

I use maven, my beans.xml is found under src/main/webapp/META-INF but I'v tried to put it in src/main/webapp/WEB-INF/classes without success.

Here is my code :

The class to inject :

@Stateless
public class Authenticator {

    @Inject
    HashGenerator hashGenerator;

    @Inject
    UserPersistance userPersistance;

    public boolean authenticate(final String username, final String password) {
        User user = userPersistance.getUser(username);
        String salt = user.getSalt();
        String hash = hashGenerator.hash(password, salt);
        return user.getPassword().equals(hash);
    }
}

The controller which throw NullPointerException :

@Stateless
public class LoginController {

    @Inject
    Authenticator authenticator;

    public void login(String username, String password) {
        if (authenticator.authenticate(username, password)) {
            UI ui = UI.getCurrent();
            ui.getSession().setAttribute(SessionAttribute.USER.getAttributeName(), username);
            ui.getNavigator().navigateTo(MainView.getName());
        }
    }
}

And my beans.xml (Under src/main/webapp/META-INF)

<beans
    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/beans_1_1.xsd"
    bean-discovery-mode="all">
</beans>

What did I do wrong?


UPDATE

Sorry, I previously miswritten the folders name of beans.xml.

So, just to be clear, maven generate a WAR archive, and I've previously tried to put beans.xml under META-INF , WEB-INF and WEB-INF/classes. None of those folder seems to make it work. I've checked (tried and it works) a quickstart project from JBoss AS 7, and they put beans.xml under WEB-INF. I've done the same.

I think that maybe it comes from my Maven configuration. Here it is :

<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>be.normegil</groupId>
    <artifactId>datamanager</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>

    <name>datamanager</name>

    <properties>
        <endorsed.dir>${project.build.directory}/endorsed</endorsed.dir>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.target>1.7</maven.compiler.target>
        <maven.compiler.source>1.7</maven.compiler.source>        
        <failOnMissingWebXml>false</failOnMissingWebXml>
        <maven.build.timestamp.format>yyyy-MM-dd'T'HH:mm:ss</maven.build.timestamp.format>
        <vaadin.version>7.1.9</vaadin.version>
        <vaadin.plugin.version>${vaadin.version}</vaadin.plugin.version>
    </properties>
    <pluginRepositories>
        <pluginRepository>
            <id>vaadin-snapshots</id>
            <url>http://oss.sonatype.org/content/repositories/vaadin-snapshots/</url>
            <releases>
                <enabled>false</enabled>
            </releases>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>
        </pluginRepository>
    </pluginRepositories>
    <dependencies>
        <dependency>
            <groupId>javax</groupId>
            <artifactId>javaee-api</artifactId>
            <version>7.0</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.enterprise</groupId>
            <artifactId>cdi-api</artifactId>
            <version>1.1</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.inject</groupId>
            <artifactId>javax.inject</artifactId>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.annotation</groupId>
            <artifactId>javax.annotation-api</artifactId>
            <version>1.2</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.ejb</groupId>
            <artifactId>javax.ejb-api</artifactId>
            <version>3.2</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.transaction</groupId>
            <artifactId>javax.transaction-api</artifactId>
            <version>1.2</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.persistence</groupId>
            <artifactId>persistence-api</artifactId>
            <version>1.0.2</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>com.vaadin</groupId>
            <artifactId>vaadin-server</artifactId>
            <version>${vaadin.version}</version>
        </dependency>
        <dependency>
            <groupId>com.vaadin</groupId>
            <artifactId>vaadin-client-compiled</artifactId>
            <version>${vaadin.version}</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
        </dependency>
        <dependency>
            <groupId>com.vaadin</groupId>
            <artifactId>vaadin-themes</artifactId>
            <version>${vaadin.version}</version>
        </dependency>
        <dependency>
            <groupId>com.vaadin</groupId>
            <artifactId>vaadin-cdi</artifactId>
            <version>1.0.0.alpha1</version>
        </dependency>
        <dependency>
            <groupId>org.mockito</groupId>
            <artifactId>mockito-all</artifactId>
            <version>1.9.5</version>
        </dependency>
        <dependency>
            <groupId>org.apache.derby</groupId>
            <artifactId>derby</artifactId>
            <version>10.7.1.1</version>
        </dependency>
    </dependencies>
    <build>
        <finalName>${project.artifactId}</finalName>
        <plugins>
            <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>
            <plugin>
                <groupId>org.wildfly.plugins</groupId>
                <artifactId>wildfly-maven-plugin</artifactId>
                <version>1.0.0.Beta1</version>
            </plugin>
        </plugins>
    </build>

</project>

回答1:

So, I was able to fix my problem, here is what I've done :

Maven dependencies

I was assuming that javax:javaee-api was enough to use the functionnalities of Java EE 7. I've added dependencies to javax.enterprise:cdi-api, javax.inject:javax.inject and javax.annotation:javax.annotation-api

beans.xml

It's only one big project build into a war archive. I've put my beans.xml under src/main/webapp/WEB-INF (Is it necessary to have it at all with Wildfly ? Don't know)

Vaadin CDIUI

That's what solved my issue. I've tried to use Vaadin CDIUI without success. Vaadin was actually initializing my UI class with a new operation. Since it was not managed by the container, every Injection points didn't work (I've first fix it by doing new operations on my views and controllers, falling on the problem I've described)

I've refactored everything so injection is used in the views and controllers, and I've added @CDIUI to my Vaadin UI. Last, I've also added a new parameter to my servlet configuration (UIProvider) for this result :

@Theme("chameleon-green")
@Title("Data Manager")
@CDIUI("")
public class DataManagerUI extends UI {
    @WebServlet(value = "/*",
            asyncSupported = true,
            initParams = {@WebInitParam(
                    name = "session-timeout",
                    value = "60"
            ),@WebInitParam(
                    name = "UIProvider",
                    value = "com.vaadin.cdi.CDIUIProvider"
            )}
    )
    @VaadinServletConfiguration(productionMode = false,
            ui = DataManagerUI.class,
            closeIdleSessions = true
    )
    public static class Servlet extends VaadinServlet {
    }

    [...]
}

When normally instantiated with new operation from Vaadin framework, the UI class should be given by the UIProvider when using Injection.

Thanks for the help !