tiistai 21. helmikuuta 2012

Database connection timed out, but how about retrying?

Q:


When launching my application, the database frequently times out during data source initialization. Its a server shared by many developers you see, and I would like to give it a few more tries before giving up. How could I accomplish this, I'm using commons-dbcp as connection pool implementation.

or

My web application seems to lose its database connection overnight when its not much used. The first new request seems to fail to database exception but the second request works ok. How could I make the app work from the get-go?

A:


Well, you can by giving up commons-dbcp and switching to c3p0 connection pool implementation. This user friendly library offers retry functionality that is a true time-saver.

The datasource configuration is a bit different, but here's a quick pointer with nice default values. Example uses Maven dependencies and Spring bean configuration.

Before


pom.xml

<dependency>
  <groupId>commons-dbcp</groupId>
  <artifactId>commons-dbcp</artifactId>
  <version>1.4</version>
</dependency>

(i'll bolt on the commons-dbcp version before somebody tells me hey it exists in there too!)

datasource.xml

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
  <property name="driverClassName" value="" />
  <property name="url" value="" />
  <property name="username" value="" />
  <property name="password" value="" />
</bean>

After


pom.xml

<dependency>
  <groupId>c3p0</groupId>
  <artifactId>c3p0</artifactId>
  <version>0.9.1.2</version>
</dependency>


datasource.xml

<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
  <property name="driverClass" value="" />
  <property name="jdbcUrl" value="" />
  <property name="user" value="" />
  <property name="password" value="" />
  <!-- How many times to retry before giving up -->
  <property name="acquireRetryAttempts" value="3"/>
  <!-- Change test query depending on the RDBMS implementation -->
  <property name="preferredTestQuery" value="SELECT 1"/>
</bean>

sunnuntai 6. maaliskuuta 2011

Vaadin Spring integration

Q:

What is the simplest way to integrate Spring into Vaadin? I want to able to access my Spring beans in custom Vaadin Components through annotated, automatically-injected fields. Injecting the main Application class only will not be enough.

A:

One way to enable Spring dependency injection features in Vaadin application is to use two of Spring's servlet lifecycle listeners and a custom injector. One listener handles creation of application context when the web application is initialized the first time. The second listener will activate on each request, and bind the application context to current thread. The custom injector is then called during Vaadin component initialization and is responsible for looking up application context from the current thread and injecting annotated fields of the component.

This way there will be no need for byte-weaving libraries run during compilation and other trickery. The only drawback is that each component must explicitly call the injector in its constructor. Maybe one day Vaadin will include a component instantiation listener similar to Wicket that could be used to handle this automatically.


web.xml
<web-app>

    <listener>
      <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    
    <listener>
      <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
    </listener>

    ...

</web-app>

Custom injector
public class Injector {

    public static void inject(Component component) {
        inject(component, getApplicationContext());
    }

    private static ApplicationContext getApplicationContext() {
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
        HttpServletRequest request = requestAttributes.getRequest();
        HttpSession session = request.getSession(false);
        return WebApplicationContextUtils.getRequiredWebApplicationContext(session.getServletContext());
    }

    private static void inject(Component component, ApplicationContext applicationContext) {
        AutowireCapableBeanFactory beanFactory = applicationContext.getAutowireCapableBeanFactory();
        beanFactory.autowireBeanProperties(component, AutowireCapableBeanFactory.AUTOWIRE_AUTODETECT, false);
    }
}

Vaadin component wanting to use Spring beans must call Injector.inject() during component initialization
public class ExampleComponent implements Component {

    @Autowired
    private SpringService springService;

    public ExampleComponent() {
         Injector.inject(this);
    }

}

A sample application based on Vaadin Maven archetype that demonstrates the use of this approach, download psp-vaadin-spring.zip.