Search code examples
javadependency-injectionjerseyhk2

Getting hk2 and Jersey to inject classes


How can I get Jersey to inject classes without creating and registering factories on a one-for-one basis?

I have the following config:

public class MyConfig extends ResourceConfig {
    public MyConfig() {
        register(new AbstractBinder() {
            @Override
            protected void configure() {
                bindFactory(FooFactory.class).to(Foo.class);
                bindFactory(BazFactory.class).to(Baz.class);
            }
        });
    }
}

hk2 will now successfully inject Foo and Baz:

// this works; Foo is created by the registered FooFactory and injected
@GET
@Path("test")
@Produces("application/json")
public Response getTest(@Context Foo foo) {
    // code
}

But that's not my goal. My goal is to inject objects that wrap these classes. There are many and they each consume different combinations of Foo and Baz. Some examples:

public class FooExtender implements WrapperInterface {

    public FooExtender(Foo foo) {
        // code
    }
}

public class FooBazExtender implements WrapperInterface {

    public FooBazExtender(Foo foo, Baz baz) {
        // code
    }
}

public class TestExtender implements WrapperInterface {

    public TestExtender(Foo foo) {
        // code
    }
    // code
}

And so on.

The following does not work:

// this does not work
@GET
@Path("test")
@Produces("application/json")
public Response getTest(@Context TestExtender test) {
    // code
}

I could create a factory for each and register it in my application config class, using the bindFactory syntax like I did with Foo and Baz. But that is not a good approach due to the number of objects in question.

I have read much of the hk2 documentation, and tried a variety of approaches. I just don't know enough of how hk2 actually works to come up with the answer, and it seems like a common enough problem that there should be a straightforward solution.


Solution

  • I wound up using FastClasspathScanner to grab classes from the package(s) I was interested in. Then I called the appropriate bind methods (bindAsContract or bind) in batches, as mentioned in Paul Samsotha's answer (after also adding the appropriate @Inject annotations).

    That seemed to be the most expedient method available to emulate autoscanning and avoid having to manually register each class.

    It feels like a hack and I'd be surprised if hk2 doesn't have a better method baked in.