简体   繁体   中英

HK2 equivalent of @Provides in Guice for Jersey 2

I've been using Jersey 1.X with Google Guice for dependency injection. Switching to Jersey 2.X seems to mean you need to use HK2 for dependency injection instead, I'm struggling to find a few things that I had in Guice.

In Jersey 1.X with Guice, I would have something like this for the application:

public class GuiceServletTestConfig extends GuiceServletContextListener  {
    @Override
    protected Injector getInjector() {
        return Guice.createInjector(new ServletModule(){
            @Override
            protected  void configureServlets(){
                bind(MyResource.class);
                serve("/*").with(GuiceContainer.class);
                bind(MyDAO.class).to(MyDAOSQL.class)
            }
        });
    }
}

And something like this for tests:

public class GuiceServletTestConfig extends GuiceServletContextListener  {
    @Override
    protected Injector getInjector() {
        return Guice.createInjector(new ServletModule(){
            @Override
            protected  void configureServlets(){
                bind(MyResource.class);
                serve("/*").with(GuiceContainer.class);
            }

            @Provides
            MyDAO provideMockMyDAO(){
                MyDAO dao = mock(MyDAO.class);
                return dao;
            }
        });
    }
}

Any my resrouce would look like this:

@Path("myresource")
public class MyResource {
    private MyDAO myDAO;

    @Inject
    protected void setMyDAO(MyDAO myDAO) {
        this.myDAO = myDAO;
    }

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public Response get() {
        // Do something with myDAO
        // Return response    
    }
}

That was I can define mocks for my tests and everything is good.

With Jersey 2.X however, I cannot find any equivalent for the @Provides annotation. MyResource is effectively the same. For dependency injection for the real application, I have:

public class Application extends ResourceConfig {
    public Application() {
        packages("com.my.package.resources");

        register(new AbstractBinder() {
            @Override
            protected void configure() {
                bind(MyDAOSQL.class).to(MyDAO.class);
            }
        });
    }
}

But I don't know how to provide mocks for tests. Anyone knoe how?

HK2 allows you to bind Factories that work just like @Provides. Here is the javadoc . I do think it isn't as convenient since you have to create a class that implements Factory. I may add an enhancement Jira to do a CDI style @Produces.

Also, you can continue to use Guice in Jersey (many people do) by using the Guice-HK2 bridge . There are some limitations when using the Bridge (like having to use @HK2Inject for classes created by Guice but to be injected with HK2 services), but most things do still work.

OK, so I figured out a way that works for me. One thing that threw me off was the swapping of the bind().to() from Guice to HK2. In Guice, you write:

bind(Abstract.class).to(Concrete.class)

Where as in HK2, you write:

bind(Concrete.class).to(Abstract.class)

The way to get the provides behaviour can be achieved with the following code:

public class MyResourceIT extends JerseyTest {
    @Override
    protected Application configure() {
        ResourceConfig resourceConfig = new ResourceConfig();
        resourceConfig.register(MyResource.class);

        resourceConfig.register(new AbstractBinder() {
            @Override
            protected void configure() {
                bind(provideMyDaoMock()).to(MyDao.class);
            }

            private MyDao provideMyDaoMock() {
                MyDao myDaoMock = mock(MyDao.class);
                return myDaoMock;
            }
        });
        return resourceConfig;
    }
}

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