简体   繁体   English

使用Jersey / Glassfish纠正CDI批注

[英]Correct CDI annotations with Jersey/Glassfish

Since I'm struggling on documentation about CDI, I hope this question could become a useful resource for the correct CDI annotations to use in Jersey/Glassfish. 由于我一直在努力寻找有关CDI的文档,因此我希望这个问题可以成为在Jersey / Glassfish中使用正确CDI注释的有用资源。

Say we have an application BookStore : 假设我们有一个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");
    }
}

We want to make Book entities accessible via a RESTful service: 我们希望通过RESTful服务使Book实体可访问:

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;
    }
}

So we need a DAO to access the datastore: 因此,我们需要一个DAO来访问数据存储:

package my.bookstore.dao;

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

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

And its implementation: 及其实现:

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;
     }
}

Then I want to inject the DefaultBookDAO into the RESTful service: 然后,我想将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();
   }
}

Now, when deploying the application I get: 现在,在部署应用程序时,我得到:

Unsatisfied dependencies for type BookDAO with qualifiers @Default

since I need to make CDI aware of it; 因为我需要让CDI意识到这一点; but how? 但是如何? I tried various combinations of @Named , @Default , @Model , @Singleton , @Stateless and many resources such as questions and blog articles have they own interpretation of them. 我试过的各种组合@Named@Default@Model@Singleton@Stateless等问题,并在博客文章和许多资源,有他们自己的人解释。

What are the correct, plain CDI annotation to use to make this injection work in Jersey/Glassfish? 在泽西岛/格拉斯菲什进行注射操作时,正确的普通CDI注释是什么?

Since it is a service you can annotate your DefaultBookDAO with @Stateless . 由于这是一项服务,因此可以使用@Stateless注释DefaultBookDAO

Then you need an additional class implementing the AbstractBinder class. 然后,您需要一个实现AbstractBinder类的附加类。

It should look like this for your case: 对于您的情况,应如下所示:

import org.glassfish.hk2.utilities.binding.AbstractBinder;

public class MyApplicationBinder extends AbstractBinder {
    @Override
    protected void configure() {
        bind(DefaultBookDAO.class).to(BookDAO.class);
    }
}

You have to register this class in the class where you extend ResourceConfig like this: 您必须在扩展ResourceConfig的类中注册该类,如下所示:

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

Then the @Inject should work. 然后@Inject应该工作。

See also: 也可以看看:

To me, it seems that you did not put beans.xml file into your application. 对我来说,您似乎没有将beans.xml文件放入应用程序中。 With Glassfish 4 (generally with Java EE 7) this file is not required, however, if you omit it, only beans annotated with scope annotations are considered. 对于Glassfish 4(通常是Java EE 7),不需要此文件,但是,如果省略它,则仅考虑使用范围注释进行注释的bean。 Therefore, as DefaultBookDAO is not marked by any annotation, it is not considered by CDI as a candidate for injection. 因此,由于DefaultBookDAO未被任何批注标记,因此CDI不会将其视为注射候选对象。

You have 2 options to fix it and make CDI mechanism consider DefaultBookDAO: 您有2个选项可以修复它,并使CDI机制考虑DefaultBookDAO:

  • put @Dependent annotation on DefaultBookDAO class - this will not change its scope, as @Dependent is the default scope, but will make CDI to consider this class @Dependent注释放在DefaultBookDAO类上-这不会更改其范围,因为@Dependent是默认范围,但会使CDI考虑此类
  • create beans.xml file in either META-INF or WEB-INF (for web apps) with the value of bean-discovery-mode="all" 在META-INF或WEB-INF(对于Web应用程序)中使用bean-discovery-mode="all"的值创建beans.xml文件

In my opinion, the first option is cleaner - you may easily separate code which can be injected and which cannot. 我认为,第一种选择是更清洁-您可以轻松地分离可以注入和不能注入的代码。 But if you want to increase productivity by omitting unnecessary annotations, go with the second option. 但是,如果您想通过省略不必要的注释来提高生产率,请选择第二个选项。 It is more complicated, but you have to do it only once per module. 它更加复杂,但是每个模块只需执行一次。

Please see this oracle blog post about beans.xml in Java EE 7 and the default behavior if it is omitted. 请参阅关于Java EE 7中bean.xml的Oracle博客文章以及默认行为(如果省略)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM