Search code examples
javatomcatdatabase-connectionguicestripes

Managing database connections with Stripes, Guice


I'm wondering about best practices to use for managing database connections in Stripes with Guice. Ideally I would want to enforce the following:

One db connection is used per thread/http request (possibly with guice binding the connection to a provider with the ServletScope.REQUEST scope) All queries are performed in one transaction, and then commited or rolled back at the end.

My question is: What should be creating/closing my database connections?

Is it a bad idea to use a Stripes Interceptor to open and close the connections?

I have a large connection of Manager classes which all perform custom SQL queries for various tables in my database. Currently all these Manager classes have a method like the following:

public abstract class MyManagerBase implements IMyManager {
  @Inject
  public void setConnection(Connection conn) {
    this.conn = conn;
   }
}

The managers themselves subclass this and don't create or close the connection.

I have action beans like this:

public class MyActionBean implements ActionBean {
  @Inject IMyManager myManager;

  @DefaultHandler
  public Resolution save() {
    myManager.doStuff(...);
  }

  ...
}

I have a guice config like this:

public class MyConfigModule extends AbstractModule {

@Override
protected void configure() {

  install(new ServletModule());
  bind(IMyManager.class).to(MyManagerImpl.class);
  bind(Connection.class).toProvider(MyConnectionProvider.class).in(ServletScopes.REQUEST);
}    

So far what I'm thinking is using an interceptor to inject the managers and at the same time, the same connection into all the managers for that http request.

My interceptor attempt is looking like this so far:

@Override
public Resolution intercept(ExecutionContext executionContext) throws Exception {
 Connection conn = null;

 switch( executionContext.getLifecycleStage() ) {
  case ActionBeanResolution:
    log.debug("Intercepting: ActionBeanResolution");
    // Inject dependencies into ActionBeans
    injector.injectMembers( executionContext.getActionBeanContext() );    
    Resolution resolution = executionContext.proceed();
    injector.injectMembers( executionContext.getActionBean() );

    return resolution;
  case RequestComplete:
    log.debug("Intercepting: RequestComplete");

    executionContext.getActionBean();

    Connection conn = injector.getInstance(Connection.class);

    conn.commit();
    conn.close();
  }
}
}

Solution

  • Is it a bad idea to use a Stripes Interceptor to open and close the connections?

    No not at all, using a Servlet filter or a Stripe Interceptor is quite a common approach for implementing the session per request pattern (session per operation is indeed an anti-pattern). Although that does not have to mean you need to start and stop transactions there as well. You could for example do explicit commits in the action bean.

    For injecting Stripes Action Beans there are however more elegant methods than using an interceptor. The stripes configuration in the web.xml offers a way to configure your own Action Bean factory with the ActionResolver.Class parameter. As the factory does actually instantiate the Action Beans, it can also inject the constructor parameters. It's not very difficult to implement this yourselves.

    But you don’t have to implement this yourself, there is an excellent Stripes plugin that handles injecting Action Beans, Action Bean Context and Interceptors: Stripes Guice. It's very simple to use see: how-to: guice managed action beans