diff --git a/.gitignore b/.gitignore index a2f6da8..4cb2ea1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ .gradle .idea build +out *.iml \ No newline at end of file diff --git a/build.gradle b/build.gradle index 825fc96..bc2cc1c 100644 --- a/build.gradle +++ b/build.gradle @@ -13,6 +13,8 @@ dependencies { compileOnly "io.dropwizard:dropwizard-jdbi:$dropwizardVersion" testCompile "junit:junit:$junitVersion" + testCompile "com.h2database:h2:1.4.197" + testCompile "io.dropwizard:dropwizard-jdbi:$dropwizardVersion" } compileJava { diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index bf3de21..a95009c 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-4.9-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/local.yml b/local.yml index 215ffbd..45d94f4 100644 --- a/local.yml +++ b/local.yml @@ -3,4 +3,4 @@ database: driverClass: org.h2.Driver user: test password: test - url: jdbc:h2:mem \ No newline at end of file + url: jdbc:h2:mem:db \ No newline at end of file diff --git a/src/main/java/net/winterly/dropwizard/hk2bundle/jdbi/HandleFactory.java b/src/main/java/net/winterly/dropwizard/hk2bundle/jdbi/HandleFactory.java new file mode 100644 index 0000000..b9d410a --- /dev/null +++ b/src/main/java/net/winterly/dropwizard/hk2bundle/jdbi/HandleFactory.java @@ -0,0 +1,32 @@ +package net.winterly.dropwizard.hk2bundle.jdbi; + +import org.glassfish.hk2.api.Factory; +import org.glassfish.jersey.process.internal.RequestScoped; +import org.skife.jdbi.v2.DBI; +import org.skife.jdbi.v2.Handle; + +import javax.inject.Inject; +import javax.inject.Provider; +import javax.inject.Singleton; + +@Singleton +public class HandleFactory implements Factory { + + private final Provider dbi; + + @Inject + public HandleFactory(Provider dbi) { + this.dbi = dbi; + } + + @Override + @RequestScoped + public Handle provide() { + return dbi.get().open(); + } + + @Override + public void dispose(Handle instance) { + instance.close(); + } +} diff --git a/src/main/java/net/winterly/dropwizard/hk2bundle/jdbi/JDBIBinder.java b/src/main/java/net/winterly/dropwizard/hk2bundle/jdbi/JDBIBinder.java index 8215743..d92957c 100644 --- a/src/main/java/net/winterly/dropwizard/hk2bundle/jdbi/JDBIBinder.java +++ b/src/main/java/net/winterly/dropwizard/hk2bundle/jdbi/JDBIBinder.java @@ -4,7 +4,6 @@ import io.dropwizard.db.DatabaseConfiguration; import org.glassfish.hk2.api.Factory; import org.glassfish.hk2.utilities.binding.AbstractBinder; -import org.glassfish.hk2.utilities.binding.ServiceBindingBuilder; import org.skife.jdbi.v2.DBI; import javax.inject.Singleton; @@ -13,30 +12,55 @@ import static java.util.Objects.requireNonNull; +/** + * HK2 binder used to configure sql objects injection + * + * @param application configuration type that contains {@link io.dropwizard.db.PooledDataSourceFactory} + */ public class JDBIBinder extends AbstractBinder { private Class> dbiFactory = JDBIFactory.class; private Class> sqlObjectFactory = SqlObjectFactory.class; - private DatabaseConfiguration databaseConfiguration; + private DatabaseConfiguration databaseConfiguration; private HashSet> sqlInterfaces = new HashSet<>(); - public JDBIBinder setDatabaseConfiguration(DatabaseConfiguration databaseConfiguration) { + /** + * @param databaseConfiguration database configuration provider + */ + public JDBIBinder(DatabaseConfiguration databaseConfiguration) { this.databaseConfiguration = requireNonNull(databaseConfiguration); - return this; } + /** + * Set factory that creates DBI instance + * + * @param dbiFactory dbi factory type + * @return self + */ public JDBIBinder setDBIFactory(Class> dbiFactory) { this.dbiFactory = requireNonNull(dbiFactory); return this; } + /** + * Set SQL object proxy factory + * + * @param sqlObjectFactory proxy factory type + * @return self + */ public JDBIBinder setSqlObjectFactory(Class> sqlObjectFactory) { this.sqlObjectFactory = requireNonNull(sqlObjectFactory); return this; } - public JDBIBinder addSqlObjects(Class... interfaces) { + /** + * Register list of JDBI interfaces + * + * @param interfaces interfaces + * @return self + */ + public JDBIBinder register(Class... interfaces) { Collections.addAll(sqlInterfaces, interfaces); return this; } @@ -44,10 +68,13 @@ public JDBIBinder addSqlObjects(Class... interfaces) { @Override protected void configure() { bind(databaseConfiguration).to(DatabaseConfiguration.class); - bindFactory(dbiFactory).to(DBI.class).in(Singleton.class); - ServiceBindingBuilder binding = bindFactory(sqlObjectFactory); - sqlInterfaces.forEach(binding::to); - binding.in(Singleton.class); + addActiveFactoryDescriptor(dbiFactory); + addActiveFactoryDescriptor(HandleFactory.class); + + sqlInterfaces.forEach(type -> bindFactory(sqlObjectFactory) + .to(type) + .in(Singleton.class) + ); } } diff --git a/src/main/java/net/winterly/dropwizard/hk2bundle/jdbi/JDBIFactory.java b/src/main/java/net/winterly/dropwizard/hk2bundle/jdbi/JDBIFactory.java index 3063019..15bcf75 100644 --- a/src/main/java/net/winterly/dropwizard/hk2bundle/jdbi/JDBIFactory.java +++ b/src/main/java/net/winterly/dropwizard/hk2bundle/jdbi/JDBIFactory.java @@ -2,34 +2,38 @@ import io.dropwizard.Configuration; import io.dropwizard.db.DatabaseConfiguration; +import io.dropwizard.db.PooledDataSourceFactory; import io.dropwizard.jdbi.DBIFactory; import io.dropwizard.setup.Environment; import org.glassfish.hk2.api.Factory; import org.skife.jdbi.v2.DBI; import javax.inject.Inject; +import javax.inject.Singleton; +@Singleton public class JDBIFactory implements Factory { private final DBIFactory factory = new DBIFactory(); private final String name = getClass().getSimpleName(); - @Inject - private Environment environment; - - @Inject - private Configuration configuration; + private final Environment environment; + private final Configuration configuration; + private final DatabaseConfiguration databaseConfiguration; @Inject - private DatabaseConfiguration databaseConfiguration; + public JDBIFactory(Environment environment, Configuration configuration, + DatabaseConfiguration databaseConfiguration) { + this.environment = environment; + this.configuration = configuration; + this.databaseConfiguration = databaseConfiguration; + } @Override + @Singleton public DBI provide() { - return factory.build( - environment, - databaseConfiguration.getDataSourceFactory(configuration), - name - ); + PooledDataSourceFactory dataSourceFactory = databaseConfiguration.getDataSourceFactory(configuration); + return factory.build(environment, dataSourceFactory, name); } @Override diff --git a/src/main/java/net/winterly/dropwizard/hk2bundle/jdbi/SqlObjectFactory.java b/src/main/java/net/winterly/dropwizard/hk2bundle/jdbi/SqlObjectFactory.java index 21df8be..a3a0530 100644 --- a/src/main/java/net/winterly/dropwizard/hk2bundle/jdbi/SqlObjectFactory.java +++ b/src/main/java/net/winterly/dropwizard/hk2bundle/jdbi/SqlObjectFactory.java @@ -6,24 +6,31 @@ import org.skife.jdbi.v2.DBI; import javax.inject.Inject; +import javax.inject.Provider; +import javax.inject.Singleton; +@Singleton public class SqlObjectFactory implements Factory { - @Inject - private InstantiationService instantiationService; + private final InstantiationService instantiationService; + private final Provider dbi; @Inject - private DBI dbi; + public SqlObjectFactory(InstantiationService instantiationService, Provider dbi) { + this.instantiationService = instantiationService; + this.dbi = dbi; + } @Override public Object provide() { Injectee injectee = instantiationService.getInstantiationData().getParentInjectee(); Class daoInterface = (Class) injectee.getRequiredType(); - return dbi.onDemand(daoInterface); + + return dbi.get().onDemand(daoInterface); } @Override public void dispose(Object instance) { - dbi.close(instance); + dbi.get().close(instance); } } diff --git a/src/test/java/net/winterly/dropwizard/hk2bundle/ExampleApp.java b/src/test/java/net/winterly/dropwizard/hk2bundle/ExampleApp.java index 289622d..bfa7448 100644 --- a/src/test/java/net/winterly/dropwizard/hk2bundle/ExampleApp.java +++ b/src/test/java/net/winterly/dropwizard/hk2bundle/ExampleApp.java @@ -3,6 +3,7 @@ import io.dropwizard.Application; import io.dropwizard.setup.Bootstrap; import io.dropwizard.setup.Environment; +import net.winterly.dropwizard.hk2bundle.jdbi.ExampleDAO; import net.winterly.dropwizard.hk2bundle.jdbi.JDBIBinder; import net.winterly.dropwizard.hk2bundle.jdbi.JDBIFactory; import net.winterly.dropwizard.hk2bundle.jdbi.SqlObjectFactory; @@ -12,15 +13,15 @@ public class ExampleApp extends Application { @Override public void initialize(Bootstrap bootstrap) { - JDBIBinder jdbiBinder = new JDBIBinder() + ExampleAppBinder appBinder = new ExampleAppBinder(); + JDBIBinder jdbiBinder = new JDBIBinder(configuration -> configuration.database) .setDBIFactory(JDBIFactory.class) .setSqlObjectFactory(SqlObjectFactory.class) - .setDatabaseConfiguration(configuration -> configuration.database); - HK2Bundle hk2Bundle = new HK2Bundle( - new ExampleAppBinder(), - jdbiBinder - ); + .register(ExampleDAO.class); + + + HK2Bundle hk2Bundle = new HK2Bundle(appBinder, jdbiBinder); bootstrap.addBundle(hk2Bundle); } diff --git a/src/test/java/net/winterly/dropwizard/hk2bundle/ExampleAppBinder.java b/src/test/java/net/winterly/dropwizard/hk2bundle/ExampleAppBinder.java index 1e21cc6..d4ae821 100644 --- a/src/test/java/net/winterly/dropwizard/hk2bundle/ExampleAppBinder.java +++ b/src/test/java/net/winterly/dropwizard/hk2bundle/ExampleAppBinder.java @@ -1,14 +1,10 @@ package net.winterly.dropwizard.hk2bundle; import net.winterly.dropwizard.hk2bundle.health.ExampleHealthCheck; -import net.winterly.dropwizard.hk2bundle.jdbi.ExampleDAO; -import net.winterly.dropwizard.hk2bundle.jdbi.SqlObjectFactory; import net.winterly.dropwizard.hk2bundle.metric.ExampleGauge; import net.winterly.dropwizard.hk2bundle.spi.DropwizardBinder; import net.winterly.dropwizard.hk2bundle.validation.InjectValidatorBundle; -import javax.inject.Singleton; - public class ExampleAppBinder extends DropwizardBinder { @Override protected void configure() { @@ -16,9 +12,5 @@ protected void configure() { metric(ExampleGauge.class); healthCheck(ExampleHealthCheck.class); - - bindFactory(SqlObjectFactory.class) - .to(ExampleDAO.class) - .in(Singleton.class); } } diff --git a/src/test/java/net/winterly/dropwizard/hk2bundle/jdbi/ExampleDAO.java b/src/test/java/net/winterly/dropwizard/hk2bundle/jdbi/ExampleDAO.java index 02c9820..31182af 100644 --- a/src/test/java/net/winterly/dropwizard/hk2bundle/jdbi/ExampleDAO.java +++ b/src/test/java/net/winterly/dropwizard/hk2bundle/jdbi/ExampleDAO.java @@ -1,10 +1,13 @@ package net.winterly.dropwizard.hk2bundle.jdbi; +import org.glassfish.hk2.api.UseProxy; +import org.skife.jdbi.v2.sqlobject.Bind; import org.skife.jdbi.v2.sqlobject.SqlQuery; +@UseProxy public interface ExampleDAO { @SqlQuery("SELECT :i") - int selectNumber(int i); + int selectNumber(@Bind("i") int i); } diff --git a/src/test/java/net/winterly/dropwizard/hk2bundle/resource/ExampleResource.java b/src/test/java/net/winterly/dropwizard/hk2bundle/resource/ExampleResource.java index d876c2c..ba7ee36 100644 --- a/src/test/java/net/winterly/dropwizard/hk2bundle/resource/ExampleResource.java +++ b/src/test/java/net/winterly/dropwizard/hk2bundle/resource/ExampleResource.java @@ -3,11 +3,7 @@ import net.winterly.dropwizard.hk2bundle.jdbi.ExampleDAO; import javax.inject.Inject; -import javax.validation.Valid; -import javax.ws.rs.Consumes; -import javax.ws.rs.POST; -import javax.ws.rs.Path; -import javax.ws.rs.Produces; +import javax.ws.rs.*; import javax.ws.rs.core.MediaType; @Produces(MediaType.APPLICATION_JSON) @@ -18,21 +14,9 @@ public class ExampleResource { @Inject private ExampleDAO dao; - @POST + @GET @Path("ping") - public Pong ping(@Valid Ping ping) { - return new Pong(ping); - } - - public static class Ping { - public int value; - } - - public static class Pong { - public final int value; - - public Pong(Ping ping) { - this.value = ping.value; - } + public int ping(@QueryParam("value") int value) { + return dao.selectNumber(value); } }