简体   繁体   中英

Jersey HK2 injection with a Generic class

I have a generic class that looks like this.

public class DAO<T> {

    private final Class<T> clazz;

    public DAO(Class<T> clazz) {
        this.clazz = clazz;
    }
}

I use it within a RestFull api powered by Jersey. I use it very often and I have to instanciate it like this for now :

private final DAO<Account> accountDAO = new DAO<>(Account.class);

I would like instantiate it using Jersey's HK2 injection library. Like this

@Inject
private final DAO<Account> accountDAO

I am having trouble finding a way to do that kind of injection with type inference. I have looked at factories (org.glassfish.hk2.api.Factory), but haven't found a way to handle inference.

Any ideas how it could be done?

I am making the assumption here that you actually need clazz in your DAO implementation

As I always have this solution up my sleeve, I am going to suggest it here as well: You could define a custom Injection Resolver that handles the creation of your DAO (make sure to register it with your application/binder) using generics. If you dont need the clazz , the code could probably be simplified a lot.

Still, I hope there is an easier way, but as I said, this works:

@Classes({ MyTest.TestInjectionResolver.class, MyTest.DAO.class })
public class MyTest extends HK2Runner {

    @Inject
    private DAO<Integer> service;

    @Test
    public void doTest() {
        assertNotNull(service);
    }

    @Service
    public static class DAO<T> {

        private final Class<T> clazz;

        @Inject
        public DAO(final Class<T> clazz) {
            this.clazz = clazz;
        }
    }

    @Singleton
    @Rank(Integer.MAX_VALUE)
    @org.jvnet.hk2.annotations.Service
    public static class TestInjectionResolver
            implements org.glassfish.hk2.api.InjectionResolver<Inject> {

        private final org.glassfish.hk2.api.InjectionResolver<Inject> injectionResolver;

        @Inject
        public TestInjectionResolver(
                @Named(org.glassfish.hk2.api.InjectionResolver.SYSTEM_RESOLVER_NAME) final org.glassfish.hk2.api.InjectionResolver<Inject> injectionResolver) {
            this.injectionResolver = injectionResolver;
        }

        @SuppressWarnings("unchecked")
        @Override
        public Object resolve(final Injectee injectee, final ServiceHandle<?> root) {
            final Type requiredType = injectee.getRequiredType();
            if (requiredType instanceof ParameterizedType) {
                final Type rawType = ((ParameterizedType) requiredType).getRawType();
                if (rawType.equals(DAO.class)) {
                    final Class<?> typeArg = (Class<?>) ((ParameterizedType) requiredType).getActualTypeArguments()[0];
                    try {
                        return ((Class<DAO<?>>) rawType).getConstructor(Class.class).newInstance(typeArg);
                    } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }
            return injectionResolver.resolve(injectee, root);
        }

        @Override
        public boolean isConstructorParameterIndicator() {
            return injectionResolver.isConstructorParameterIndicator();
        }

        @Override
        public boolean isMethodParameterIndicator() {
            return injectionResolver.isMethodParameterIndicator();
        }

    }

}

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