Syed
Syed

Reputation: 1452

jdbi, guice with dropwizard

Hello I am trying to create an application using dropwizard framework. I have the DAO classes impl which needs an handle to connection manager instance which will then be used to get database connections. I have a multi tenant database application. This connection manager would be a custom implementation.

The application uses hikari cp as connection pool and mysql database. I want to initialize the datasource and connection pool using dropwizard managed object feature. Once the datasource is initialized I want to inject the connection manager instance in each of dao classes using guice binding something like

bind(ConnectionManager.class).toProvider(ConnectionManagerProvider.class);

Then in each dao impl classes

@Inject
public class UserDAOIpl extends AbstractDAO {
    protected UserDAOImpl(ConnectionManager connectionManager) {
        super(connectionManager);
    }
}

I have looked everywhere on the net there is no particular example for my use case. Also there is a lack of documentation at dropwirzard.io

This is more of an architectural design question rather than code question.

The datasource module would be a separate module which would be used in many service. I am using maven as build tool.

My questions are

  1. How I can approach this situation ? Some class names and implementation guide lines would be very useful.
  2. The application would be handing half a million requests a day. The solution should be feasible.

I look forward to community for any guidance or if any body can point me to some good resources.

NOTE: We won't be using hibernate for this application and would be using JDBI.

Upvotes: 8

Views: 5258

Answers (2)

pandaadb
pandaadb

Reputation: 6456

I can't comment, but wanted to add on to Alex's answer:

For the repository implementation, I recommend having the repository be handled by jDBI instead of using Guice. Here's what I did:

In the Guice module, add a provide method:

@Provides
@Singleton
public void repository(Dbi dbi) {
    // dbi.onDemand(whateverYourClassIs.class)
}

in the repository class, use @CreateSqlObject to have your DAOs available:

public abstract class Repo {
    @CreateSqlObject
    abstract Dao dao(); // will return a jDBI managed DAO impl

    public void doWhatever() {
       /// logic
    }
}

This has the distinct advantage that you can now use jDBI annotations. (I have not found a way to use them with guice directly). This is very nice for example, if you need to execute DAO code in a transaction. The Repository is still handled within Guice so it can be injected anywhere, but jDBI handles the tricky bits within your DAO/Repository code.

Hope this helps :)

Artur

Upvotes: 0

ahus1
ahus1

Reputation: 5940

I prepared a setup similar to the one you described as follows. It sets up guice, initializes a DBIFactory (you might need to adopt that part to your scenario). Then a JDBI object is handed over to a repository implementation that can use it to persist an entity of type Vessel.

(1) Adding guice to the project

<dependency>
  <groupId>com.hubspot.dropwizard</groupId>
  <artifactId>dropwizard-guice</artifactId>
  <version>x.x.x</version>
</dependency>

(2) Setup Guice in initialize():

guiceBundle = GuiceBundle.<YourConfiguration>newBuilder()
        .addModule(new GuiceModule())
        .enableAutoConfig("your.package.name.heres")
        .setConfigClass(YourConfiguration.class)
        .build();

(3) Guice config for preparing JDBI elements

public class GuiceModule extends AbstractModule {

    private DBI jdbi;

    @Provides
    public DBI prepareJdbi(Environment environment,
                           SightingConfiguration configuration) throws ClassNotFoundException {
        // setup DB access including DAOs
        // implementing a singleton pattern here but avoiding 
        // Guice to initialize DB connection too early
        if (jdbi == null) {
            final DBIFactory factory = new DBIFactory();
            jdbi = factory.build(environment, configuration.getDataSourceFactory(), "h2");
        }
        return jdbi;
    }

    @Provides
    public VesselJDBI prepareVesselJdbi(DBI jdbi) {
        return jdbi.onDemand(VesselJDBI.class);
    }

    @Override
    protected void configure() {
        bind(VesselRepository.class).to(VesselRepositoryImpl.class);
        /* ... */
    }
}

(4) start using it in your classes

public class VesselRepositoryImpl implements VesselRepository {

    private VesselJDBI jdbi;    

    @Inject
    public VesselRepositoryImpl(VesselJDBI jdbi) {
        this.jdbi = jdbi;
    }

    public Vessel create(Vessel instance) {
        return jdbi.inTransaction((transactional, status) -> {
            /* do several things with jdbi in a transactional way */
        });
    }

}

(please note: the last code example used Java 8. To use JDBI with Java 8 with Dropwizard 0.8.1 please use jdbi version 2.62 to avoid bug https://github.com/jdbi/jdbi/issues/144)

Please let me know if this helped you.

Best regards,

Alexander

Upvotes: 8

Related Questions