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

时间:2016-08-24 06:39:02

标签: cdi java-ee-7 websphere-liberty

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

然而,注入失败,除非我在注入的bean上指定范围注释(例如@ApplicationScoped),尽管根据许多在线教程(例如this),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();
    }

}

HelloService.java

package my.simple.app;

public class HelloService {
    String createHelloMessage(String name) {
        return "Hello " + name + "!";
    }
}

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>

但是我收到此错误

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.

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

我做错了什么?

解决方案

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

中启用显式发现模式

链接:

3 个答案:

答案 0 :(得分:5)

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

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

<?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>

或者,在WDT中,您可以通过右键单击项目并选择 Java EE Tools - &gt;来生成此项。生成CDI Bean部署描述符存根,并确保从下拉菜单“Bean发现模式”选择中选择all

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

答案 1 :(得分:3)

虽然斯科特建议解决你的问题,但这里有关于它如何运作的全貌。

在CDI 1.2中,默认情况下所有应用程序都启用了CDI。

如果存在空beans.xml或带有bean-discovery-mode =&#34; all&#34;的beans.xml,则所有类都选择使用bean。

如果没有带bean-discovery-mode =&#34;注释&#34;的beans.xml或beans.xml,将扫描每个类的bean。只有使用bean定义注释(https://docs.jboss.org/cdi/spec/1.2/cdi-spec.html#bean_defining_annotations)注释的类才被视为bean。

在您的第一个示例中,由于您没有beans.xml,因此执行了对bean定义注释的扫描。由于未找到定义注释的bean,因此禁用了cdi。结果,注射失败了。

要启用注射,有两种解决方案: 1.使用定义注释的bean注释类HelloService(例如,任何范围:ApplicationScoped,RequestScoped,SessionScoped,ConversationScoped,Dependent等)。这将使HelloService成为CDI bean,然后注入将成功。 2.使用beans-discovery-mode =&#34; all&#34;添加空beans.xml或beans.xml。在.war文件的WEB-INF下或.jar文件的META-INF

有关bean档案的更多信息,请参阅https://docs.jboss.org/cdi/spec/1.2/cdi-spec.html#bean_archive

答案 2 :(得分:0)

我对EJB不够熟悉,但您可以尝试将@Stateless或@Service注释添加到Service类

package my.simple.app;
@Stateless
//@Service
public class HelloService {
    String createHelloMessage(String name) {
        return "Hello " + name + "!";
    }
}

修改 或者,如果您在使用生产者方法 http://docs.oracle.com/javaee/6/tutorial/doc/gjdid.html

之后无法修改 HelloService