package ru.vyarus.dropwizard.guice.module.installer.feature.jersey; import com.google.inject.Binder; import com.google.inject.Injector; import io.dropwizard.setup.Environment; import org.glassfish.hk2.utilities.binding.AbstractBinder; import ru.vyarus.dropwizard.guice.module.installer.FeatureInstaller; import ru.vyarus.dropwizard.guice.module.installer.install.JerseyInstaller; import ru.vyarus.dropwizard.guice.module.installer.install.TypeInstaller; import ru.vyarus.dropwizard.guice.module.installer.install.binding.BindingInstaller; import ru.vyarus.dropwizard.guice.module.installer.order.Order; import ru.vyarus.dropwizard.guice.module.installer.util.FeatureUtils; import ru.vyarus.dropwizard.guice.module.installer.util.JerseyBinding; import javax.inject.Singleton; import javax.ws.rs.Path; import static ru.vyarus.dropwizard.guice.module.installer.util.JerseyBinding.isHK2Managed; /** * Jersey resource installer. * Search classes annotated with {@link Path} or implementing interfaces annotated with {@link Path} * (only directly implemented). Directly register instance in jersey context to force singleton. * If we register it by type, then we could use prototype beans (resource instance created on each request), * which will lead to performance overhead. To ovoid misuse, singleton resources are forced. Override installer * if you really need prototype resources. * * @author Vyacheslav Rusakov * @since 01.09.2014 */ @Order(40) public class ResourceInstaller implements FeatureInstaller<Object>, BindingInstaller, TypeInstaller<Object>, JerseyInstaller<Object> { @Override public boolean matches(final Class<?> type) { return !type.isInterface() && (FeatureUtils.hasAnnotation(type, Path.class) || hasMatchedInterfaces(type)); } @Override public <T> void install(final Binder binder, final Class<? extends T> type, final boolean lazy) { if (!isHK2Managed(type) && !lazy) { // force singleton binder.bind(type).in(Singleton.class); } } @Override public void install(final Environment environment, final Class<Object> type) { // type registration is required to properly start resource environment.jersey().register(type); } @Override public void install(final AbstractBinder binder, final Injector injector, final Class<Object> type) { JerseyBinding.bindComponent(binder, injector, type); } @Override public void report() { // dropwizard logs installed resources } private boolean hasMatchedInterfaces(final Class<?> type) { boolean matches = false; // looking only first interface level for (Class<?> iface : type.getInterfaces()) { if (iface.isAnnotationPresent(Path.class)) { matches = true; break; } } return matches; } }