Websphere Liberty概要文件中的Java EE依赖注入

Kir*_* G. 2 cdi websphere-liberty java-ee-7

我试图在我通过Docker安装的Websphere Liberty配置文件中运行的非常简单的Web应用程序中使用CDI.

但是注入失败,除非我@ApplicationScoped在注入的bean上指定范围注释(例如),尽管根据许多在线教程(例如,这个),Java EE规范不要求这样做.

以下是失败的代码:

HelloWorldServlet.java

package my.simple.app;

import javax.inject.Inject;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

@WebServlet("/HelloWorld")
public class HelloWorldServlet extends HttpServlet {

    static String PAGE_HEADER = "<html><head /><body>";
    static String PAGE_FOOTER = "</body></html>";

    @Inject
    HelloService helloService;

    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        PrintWriter writer = resp.getWriter();
        writer.println(PAGE_HEADER);
        writer.println("<h1>" + helloService.createHelloMessage("World") + "</h1>");
        writer.println(PAGE_FOOTER);
        writer.close();
    }

}
Run Code Online (Sandbox Code Playgroud)

HelloService.java

package my.simple.app;

public class HelloService {
    String createHelloMessage(String name) {
        return "Hello " + name + "!";
    }
}
Run Code Online (Sandbox Code Playgroud)

server.xml(Docker镜像是websphere-liberty:javaee7)

<server description="default servlet engine">

    <httpEndpoint id="defaultHttpEndpoint" host="*" httpPort="9080" httpsPort="9443" />

    <!-- Enable features -->
    <featureManager>
        <feature>servlet-3.1</feature>
        <feature>cdi-1.2</feature>
    </featureManager>

</server>
Run Code Online (Sandbox Code Playgroud)

但是我得到了这个错误

Error 404: javax.servlet.UnavailableException: SRVE0319E: For the [my.simple.app.HelloWorldServlet] servlet, my.simple.app.HelloWorldServlet servlet class was found, but a resource injection failure has occurred. The @Inject java.lang.reflect.Field.helloService reference of type my.simple.app.HelloService for the null component in the app.war module of the app application cannot be resolved.
Run Code Online (Sandbox Code Playgroud)

但是,一旦我添加@ApplicationScoped到HelloService,它就会开始工作.

我做错了什么?

方案:

在CDI1.2(我正在使用)中,默认情况下只会发现带注释的bean.要发现所有bean,需要启用显式发现模式beans.xml

链接:

Sco*_*urz 5

您可以强制CDI将servlet视为bean,并通过将bean发现模式更改为执行注入all.

本文提供了一些有用的背景知识和示例:

<?xml version="1.0" encoding="UTF-8"?>
<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>
Run Code Online (Sandbox Code Playgroud)

或者,在WDT中,您可以通过右键单击项目并选择Java EE Tools - > Generate CDI Beans Deployment Descriptor Stub来生成此项,并确保all从下拉菜单"Bean发现模式"中进行选择.

不利的一面是应用程序需要更长时间才能启动,但这是一个可以避免重新编译的权衡.