简体   繁体   中英

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.

Say we have an application 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:

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:

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:

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

What are the correct, plain CDI annotation to use to make this injection work in Jersey/Glassfish?

Since it is a service you can annotate your DefaultBookDAO with @Stateless .

Then you need an additional class implementing the AbstractBinder class.

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:

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

Then the @Inject should work.

See also:

To me, it seems that you did not put beans.xml file into your application. 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. Therefore, as DefaultBookDAO is not marked by any annotation, it is not considered by CDI as a candidate for injection.

You have 2 options to fix it and make CDI mechanism consider 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
  • create beans.xml file in either META-INF or WEB-INF (for web apps) with the value of bean-discovery-mode="all"

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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