【问题标题】:Correct CDI annotations with Jersey/Glassfish使用 Jersey/Glassfish 更正 CDI 注释
【发布时间】:2015-09-30 15:22:31
【问题描述】:

由于我在 CDI 文档上苦苦挣扎,我希望这个问题可以成为在 Jersey/Glassfish 中使用正确 CDI 注释的有用资源。

假设我们有一个应用程序BookStore

package my.bookstore;

import javax.ws.rs.ApplicationPath;
import org.glassfish.jersey.server.ResourceConfig;

@ApplicationPath("/bookstore")
public class BookStore extends ResourceConfig {
    public BookStore() {
        this.packages("my.bookstore.resource");
    }
}

我们想让Book 实体可以通过 RESTful 服务访问:

package my.bookstore.entity;

public class Book {
    public String isbn;
    public String title;
    public String author;

    public Book(String isbn, String title, String author) {
        this.isbn = isbn;
        this.title = title;
        this.author = author;
    }
}

所以我们需要一个DAO 来访问数据存储区:

package my.bookstore.dao;

import my.bookstore.entity.Book;
import java.util.List;

public interface BookDAO {
    public List<Book> getAllBooks();
}

及其实现:

package my.bookstore.dao;

import my.bookstore.entity.Book;
import java.util.List;
import java.util.ArrayList;

public class DefaultBookDAO implements BookDAO {
    public List<Book> getAllBooks() {
        List<Book> bookList = new ArrayList<>();
        list.add(new Book("1234", "Awesome Book", "Some Author"));
        return bookList;
     }
}

然后我想将DefaultBookDAO注入到RESTful服务中:

package my.bookstore.resource;

import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

@Path("/books")
public class BookResource {

   @Inject
   BookDAO dao;

   @GET
   @Produces(MediaType.APPLICATION_JSON)
   public List<Book> getBooks() {
       return this.dao.getAllBooks();
   }
}

现在,在部署应用程序时,我得到:

Unsatisfied dependencies for type BookDAO with qualifiers @Default

因为我需要让 CDI 意识到这一点;但如何?我尝试了@Named@Default@Model@Singleton@Stateless 的各种组合,问题和博客文章等许多资源都有自己的解释。

在 Jersey/Glassfish 中使用什么正确、简单的 CDI 注释来使这种注入工作?

【问题讨论】:

  • 什么版本的 glassfish?
  • @JohnAment Glassfish 4.1

标签: java dependency-injection glassfish jersey cdi


【解决方案1】:

对我来说,您似乎没有将 beans.xml 文件放入您的应用程序中。对于 Glassfish 4(通常对于 Java EE 7),不需要此文件,但是,如果您省略它,则只考虑使用范围注释进行注释的 bean。因此,由于 DefaultBookDAO 没有被任何注解标记,因此 CDI 不会将其视为注入的候选对象。

您有 2 个选项来修复它并使 CDI 机制考虑 DefaultBookDAO:

  • 在 DefaultBookDAO 类上添加 @Dependent 注释 - 这不会更改其范围,因为 @Dependent 是默认范围,但会使 CDI 考虑此类
  • 在 META-INF 或 WEB-INF(用于 Web 应用程序)中创建 beans.xml 文件,其值为 bean-discovery-mode="all"

在我看来,第一个选项更简洁——您可以轻松地分离可以注入和不能注入的代码。但是,如果您想通过省略不必要的注释来提高工作效率,请使用第二个选项。它更复杂,但每个模块只需执行一次。

请参阅this oracle blog post 了解 Java EE 7 中的 beans.xml 以及省略时的默认行为。

【讨论】:

    【解决方案2】:

    由于它是一项服务,您可以使用 @Stateless 注释您的 DefaultBookDAO

    那么你需要一个额外的类来实现AbstractBinder 类。

    你的情况应该是这样的:

    import org.glassfish.hk2.utilities.binding.AbstractBinder;
    
    public class MyApplicationBinder extends AbstractBinder {
        @Override
        protected void configure() {
            bind(DefaultBookDAO.class).to(BookDAO.class);
        }
    }
    

    你必须在你扩展ResourceConfig的类中注册这个类,如下所示:

    @ApplicationPath("/bookstore")
    public class BookStore extends ResourceConfig {
        public BookStore() {
            register(new MyApplicationBinder());
            this.packages("my.bookstore.resource");
        }
    }
    

    那么@Inject 应该可以工作了。

    另请参阅:

    【讨论】:

    • 我真的需要活页夹吗? Jersey 不应该自动寻找 BookDAO 的实现来注入吗?
    • 错误消息Unsatisfied dependencies for type BookDAO with qualifiers @Default 暗示 CDI 被用作依赖注入机制。您的建议与 HK2 机制有关,显然 Jersey 也支持该机制,但未在 Java EE 标准中指定,也未用于最新 Glassfish v4 的标准设置。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-16
    相关资源
    最近更新 更多