Страницы

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

понедельник, 3 декабря 2018 г.

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

Есть веб-приложение, в котором в файле 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


Ответ

Проблема в том, что вы создаёте 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 в конфиг каждого сервлета при такой конфигурации не нужно.

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

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