Frage

It looks like my Spring container is getting initialized twice. Thats not good! The way I found this was while getting a connection from a C3P0 connection pool. I have a C3P0 ComboPooledDataSource in my Spring context.

@Bean
@Named("comboPooledDataSource")
public ComboPooledDataSource comboPooledDataSource() {

    Properties properties = properties();

    String environment = getEnvironment();

    ComboPooledDataSource pool = new ComboPooledDataSource();
    try {
        pool.setDriverClass(properties.getProperty("com.pledgeling.platform.db.driver"));
    } catch (PropertyVetoException e) {
        e.printStackTrace();
    }
    pool.setJdbcUrl(properties.getProperty("com.company.db.dsn." + environment));
    pool.setUser(properties.getProperty("com.company.db.user." + environment));
    pool.setPassword(properties.getProperty("com.company.db.pass." + environment));
    pool.setMaxIdleTimeExcessConnections(30 * 60);
    pool.setMaxIdleTime(3 * 60 * 60);

    try {
        Connection testConnection = null;
        testConnection = pool.getConnection();
        System.out.println("Initialized Data Source " + testConnection.toString());
        testConnection.close();
    } catch (SQLException e) {
        e.printStackTrace();
    }
    return pool;
}

And that works correctly when the container is initialized:

Dec 03, 2013 4:43:49 PM com.mchange.v2.log.MLog <clinit>
INFO: MLog clients using java 1.4+ standard logging.
Dec 03, 2013 4:43:49 PM com.mchange.v2.c3p0.C3P0Registry banner
INFO: Initializing c3p0-0.9.1.2 [built 21-May-2007 15:04:56; debug? true; trace: 10]
Dec 03, 2013 4:43:50 PM com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource getPoolManager
INFO: Initializing c3p0 pool... com.mchange.v2.c3p0.ComboPooledDataSource [ acquireIncrement -> 3, acquireRetryAttempts -> 30, acquireRetryDelay -> 1000, autoCommitOnClose -> false, automaticTestTable -> null, breakAfterAcquireFailure -> false, checkoutTimeout -> 0, connectionCustomizerClassName -> null, connectionTesterClassName -> com.mchange.v2.c3p0.impl.DefaultConnectionTester, dataSourceName -> z8kflt8y1fq2h6a1npdfoy|7dd8fdd6, debugUnreturnedConnectionStackTraces -> false, description -> null, driverClass -> org.postgresql.Driver, factoryClassLocation -> null, forceIgnoreUnresolvedTransactions -> false, identityToken -> z8kflt8y1fq2h6a1npdfoy|7dd8fdd6, idleConnectionTestPeriod -> 0, initialPoolSize -> 3, jdbcUrl -> ..., maxAdministrativeTaskTime -> 0, maxConnectionAge -> 0, maxIdleTime -> 10800, maxIdleTimeExcessConnections -> 1800, maxPoolSize -> 15, maxStatements -> 0, maxStatementsPerConnection -> 0, minPoolSize -> 3, numHelperThreads -> 3, numThreadsAwaitingCheckoutDefaultUser -> 0, preferredTestQuery -> null, properties -> {user=******, password=******}, propertyCycle -> 0, testConnectionOnCheckin -> false, testConnectionOnCheckout -> false, unreturnedConnectionTimeout -> 0, usesTraditionalReflectiveProxies -> false ]
Initialized Data Source com.mchange.v2.c3p0.impl.NewProxyConnection@2df8e5e4
Dec 03, 2013 4:43:50 PM org.springframework.web.context.ContextLoader initWebApplicationContext
INFO: Root WebApplicationContext: initialization completed in 5795 ms

However, the first time I hit the database through the webapp, the connection is made again, and I'm not sure why. Here is the code that grabs the connection pool in my DAO class

private static ApplicationContext context = new AnnotationConfigApplicationContext(Config.class);

private static Connection getConnection() {
    ComboPooledDataSource comboPooledDataSource = (ComboPooledDataSource)context.getBean("comboPooledDataSource");
    try {
        return comboPooledDataSource.getConnection();
    } catch (SQLException e) {
        e.printStackTrace();
    }
    return null;
}

When this is hit, the whole container appears to be initialized again:

Dec 03, 2013 4:46:28 PM org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider registerDefaultFilters
INFO: JSR-330 'javax.inject.Named' annotation found and supported for component scanning
Dec 03, 2013 4:46:28 PM org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@db03ddc: startup date [Tue Dec 03 16:46:28 EST 2013]; root of context hierarchy
Dec 03, 2013 4:46:28 PM org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider registerDefaultFilters
INFO: JSR-330 'javax.inject.Named' annotation found and supported for component scanning
Dec 03, 2013 4:46:29 PM org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor <init>
INFO: JSR-330 'javax.inject.Inject' annotation found and supported for autowiring
Dec 03, 2013 4:46:29 PM org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@4c84f510: defining beans [org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,config,org.springframework.context.annotation.ConfigurationClassPostProcessor.importAwareProcessor,properties,jaxRsServer,comboPooledDataSource,cxf,jaxRsApiApplication,jsonProvider,serverHealthCheck,applicationHealthCheck]; root of factory hierarchy
Dec 03, 2013 4:46:30 PM com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource getPoolManager
INFO: Initializing c3p0 pool... com.mchange.v2.c3p0.ComboPooledDataSource [ acquireIncrement -> 3, acquireRetryAttempts -> 30, acquireRetryDelay -> 1000, autoCommitOnClose -> false, automaticTestTable -> null, breakAfterAcquireFailure -> false, checkoutTimeout -> 0, connectionCustomizerClassName -> null, connectionTesterClassName -> com.mchange.v2.c3p0.impl.DefaultConnectionTester, dataSourceName -> z8kflt8y1fq2h6a1npdfoy|e9fd18b, debugUnreturnedConnectionStackTraces -> false, description -> null, driverClass -> org.postgresql.Driver, factoryClassLocation -> null, forceIgnoreUnresolvedTransactions -> false, identityToken -> z8kflt8y1fq2h6a1npdfoy|e9fd18b, idleConnectionTestPeriod -> 0, initialPoolSize -> 3, jdbcUrl -> ... , maxAdministrativeTaskTime -> 0, maxConnectionAge -> 0, maxIdleTime -> 10800, maxIdleTimeExcessConnections -> 1800, maxPoolSize -> 15, maxStatements -> 0, maxStatementsPerConnection -> 0, minPoolSize -> 3, numHelperThreads -> 3, numThreadsAwaitingCheckoutDefaultUser -> 0, preferredTestQuery -> null, properties -> {user=******, password=******}, propertyCycle -> 0, testConnectionOnCheckin -> false, testConnectionOnCheckout -> false, unreturnedConnectionTimeout -> 0, usesTraditionalReflectiveProxies -> false ]
Initialized Data Source com.mchange.v2.c3p0.impl.NewProxyConnection@636ab40a

Please note: I have nto had success with the @Inject or @Autowired syntax, so if thats part of the solution please tell me where and how to use them. One more note: this is an embedded jetty 9 spring 3 zero XML uberjar. All annotation driven.

The Spring container is initialized once on Jetty start, but I have no idea why its being initialized a second time.

public class JettyStarter {

    public static void main(final String[] args) throws Exception {

        Server server = new Server(8080);
        final ServletHolder servletHolder = new ServletHolder(new CXFServlet());
        final ServletContextHandler context = new ServletContextHandler();
        context.setContextPath("/");
        context.addServlet(servletHolder, "/application/*");
        context.addEventListener(new ContextLoaderListener());
        context.setInitParameter("contextClass", AnnotationConfigWebApplicationContext.class.getName());
        context.setInitParameter("contextConfigLocation", Config.class.getName());
        server.setHandler(context);
        server.start();
        server.join();
    }
}
War es hilfreich?

Lösung

The registered ContextLoaderListener

context.addEventListener(new ContextLoaderListener());

will initialize a AnnotationConfigWebApplicationContext instance with the specified @Configuration class

context.setInitParameter("contextClass", AnnotationConfigWebApplicationContext.class.getName());
context.setInitParameter("contextConfigLocation", Config.class.getName());

This will load the context once.

You are also then loading a second copy of your context here

private static ApplicationContext context = new AnnotationConfigApplicationContext(Config.class);

This will happen when the class that contains this member is loaded and initialized.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top