2015-09-30 42 views
0

由于我在关于CDI的文档方面挣扎不已,我希望这个问题能够成为在Jersey/Glassfish中使用的正确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"); 
    } 
} 

我们希望通过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; 
    } 
} 

所以我们需要一个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注释?

+0

什么版本的玻璃鱼? –

+0

@JohnAment Glassfish 4.1 –

回答

0

对我来说,似乎你没有把beans.xml的文件到您的应用程序。对于Glassfish 4(通常使用Java EE 7),该文件不是必需的,但是,如果忽略它,则只考虑使用范围注释注释的bean。因此,由于DefaultBookDAO没有任何注释标记,它不被CDI认为是注射的候选者。

您有2个选项来解决它,使CDI机制考虑DefaultBookDAO:

  • @Dependent注释上DefaultBookDAO类 - 这不会改变它的范围,因为@Dependent是默认的范围,反而会使CDI来考虑该类
  • 在任何META-INF或WEB-INF(对于Web应用程序)创建beans.xml的文件与bean-discovery-mode="all"

的价值在我看来,第一个选项更清洁 - 您可以轻松分离可以注入和不能注入的代码。但是,如果您想通过省略不必要的注释来提高生产力,请使用第二个选项。它比较复杂,但每个模块只能执行一次。

请参阅this oracle blog post有关使用Java EE 7的beans.xml和默认行为如果忽略。

0

由于这是一项服务,您可以使用@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应该工作。

参见:

+0

我真的需要一个活页夹吗?泽西不应该自动寻找“BookDAO”的实现来注入? –

+0

错误消息'带有限定符@默认值的BookDAO类型的不满意依赖关系'提示提示CDI被用作依赖注入机制。您的建议与HK2机制有关,显然Jersey也支持该机制,但未在Java EE标准中指定,并且未用于最近Glassfish v4的标准设置。 – OndrejM