Страницы

Поиск по вопросам

пятница, 27 декабря 2019 г.

Инициализация одного пула соединений на разные сервлеты Tomcat

#java #spring #servlet #c3p0 #pool


Есть веб-приложение, в котором в файле web.xml определены два сервлета. 
Есть пул соединений c3p0, который, как я понимаю, должен инициализироваться один раз. 

НО! Если обратиться к одному сервлету, а потом к другому, то пул будет инициализирован
дважды и на каждый сервлет окажется свой пул.

Как это исправить, чтобы пул был общим? 

Конфигурация application-context.xml :




    
    



Конфигурация сервлета 1: 




    




Конфигурация сервлета 2:




    
    



Описание бинов для application-context: 

package ru.rusal.mishka.core;

import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.eclipse.persistence.jpa.PersistenceProvider;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;

import javax.persistence.EntityManagerFactory;
import javax.persistence.ValidationMode;
import javax.sql.DataSource;
import java.beans.PropertyVetoException;
import java.util.Properties;

@Configuration

public class ContextConfiguration {

    @Bean
    public DataSource dataSource(
            @Qualifier("systemConfiguration") SystemConfiguration systemConfiguration
    ) throws PropertyVetoException {
        Properties props = new Properties();
        props.setProperty("user", systemConfiguration.getDBConfig().getUser());
        props.setProperty("password", systemConfiguration.getDBConfig().getPassword());

        final ComboPooledDataSource dataSource = new ComboPooledDataSource();
        dataSource.setDriverClass("oracle.jdbc.OracleDriver");
        dataSource.setJdbcUrl("jdbc:oracle:thin:@localhost:1521:DB");
        dataSource.setInitialPoolSize(5);
        dataSource.setMaxPoolSize(20);
        dataSource.setProperties(props);

        return dataSource;
    }

    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory(
            @Qualifier("dataSource") DataSource ds
    ) {
        LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();

        factoryBean.setPersistenceUnitName("MilliService");
        factoryBean.setDataSource(ds);
        factoryBean.setPersistenceProviderClass(PersistenceProvider.class);
        factoryBean.setLoadTimeWeaver(new InstrumentationLoadTimeWeaver());
        factoryBean.setValidationMode(ValidationMode.NONE);
        factoryBean.setPackagesToScan("ru.milli.app.persistence");
        factoryBean.getJpaPropertyMap().put("eclipselink.weaving", Boolean.FALSE.toString());
        factoryBean.getJpaPropertyMap().put("eclipselink.allow-zero-id", Boolean.TRUE.toString());

        return factoryBean;
    }

    @Bean
    public JpaTransactionManager transactionManager(
            @Qualifier("entityManagerFactory") EntityManagerFactory factory
    ) throws PropertyVetoException {
        JpaTransactionManager manager = new JpaTransactionManager();
        manager.setEntityManagerFactory(factory);
        return manager;
    }
}


Для сервлетов там обычные rest-сервисы на аннотациях @RestController.

Конфиг web.xml: 




    
    mishka

    
        ru.milli.CleanupContextListener
    

    
        webportal
        org.springframework.web.servlet.DispatcherServlet
    

    
        rest
        org.springframework.web.servlet.DispatcherServlet
    

    
        rest
        /rest/*
    

    
        webportal
        *.html
    

    
        webportal
        /image.jpeg
    

    
        500
        /WEB-INF/jsp/error.jsp
    

    
        404
        /error.html
    

    
        /WEB-INF/jsp/start.jsp
    

    
        
            http://www.springframework.org/tags
            /WEB-INF/tld/spring.tld
        
        
            http://www.springframework.org/tags/form
            /WEB-INF/tld/spring-form.tld
        
    



    


Ответы

Ответ 1



Проблема в том, что вы создаёте 2 DispatcherServlet, и в оба включаете application-context.xml. Согласно документации, A web application can define any number of DispatcherServlets. Each servlet will operate in its own namespace, loading its own application context with mappings, handlers, etc. У каждого DispatcherServlet будет свой контекст Spring, а значит, бины для каждого будут создаваться по отдельности. Тег объединяет текущий конфиг с содержимым импортируемого конфига. Получается, в конфиге каждого сервлета будет объявлен свой пул соединений, и при запуске приложения он создастся два раза. Решить это можно, создав root контекст с бинами, необходимыми всем дочерним контекстам. Делается это при помощи добавления ContextLoaderListener в web.xml: org.springframework.web.context.ContextLoaderListener contextConfigLocation classpath:/path/to/application-context.xml Все бины, определённые в root контексте, будут видны в дочерних (web application) контекстах. При этом дочерний контекст может переопределить бин из родительского контекста (объявив свой бин с таким же id), поэтому включать application-context.xml в конфиг каждого сервлета при такой конфигурации не нужно.

Комментариев нет:

Отправить комментарий