Como configurar o C3P0?

Galera to com o seguinte problema. Tenho uma aplicação web, em JSF, que usa uma Thread separada para leitura de arquivos Txt. Funciona ± assim, eu envio esses arquivos por FTP e de tempo em tempo essa Thread é executada e faz a leitura desses arquivos SALVANDOS DADOS no banco.

Na verdade essa Thread é startada junto com o Glassfish, e depois faz a leitura e espera 15 minutos, pra fazer a leitura novamente. Isso é feito pq os arquivos vão ser jogados com certa frequencia.

Até aí td bem, o que acontece é que enquanto se está fazendo a leitura do arquivo(a cada linha é acessado o banco para buscar e salvar dados) e alguém loga no sistema ou acessa o banco acontece a seguinte exception:

org.hibernate.SessionException: Session is closed!
        at org.hibernate.impl.AbstractSessionImpl.errorIfClosed(AbstractSessionImpl.java:49)
        at org.hibernate.impl.SessionImpl.getBatcher(SessionImpl.java:260)
        at org.hibernate.loader.Loader.getResultSet(Loader.java:1801)
        at org.hibernate.loader.Loader.doQuery(Loader.java:674)
        at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:236)
        at org.hibernate.loader.Loader.doList(Loader.java:2220)
        at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2104)
        at org.hibernate.loader.Loader.list(Loader.java:2099)
        at org.hibernate.loader.criteria.CriteriaLoader.list(CriteriaLoader.java:94)
        at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1569)
        at org.hibernate.impl.CriteriaImpl.list(CriteriaImpl.java:283)
        at org.hibernate.impl.CriteriaImpl.uniqueResult(CriteriaImpl.java:305)
        at br.com.modelo.usuario.UsuarioDAO.getUsuarioValido(UsuarioDAO.java:30)
        at br.com.controle.publico.ControlePaginaLogin.actionValidarUsuario(ControlePaginaLogin.java:49)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at com.sun.el.parser.AstValue.invoke(AstValue.java:187)
        at com.sun.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:297)
        at com.sun.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:68)
        at com.sun.facelets.el.LegacyMethodBinding.invoke(LegacyMethodBinding.java:69)
        at com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:91)
        at javax.faces.component.UICommand.broadcast(UICommand.java:383)
        at org.ajax4jsf.component.AjaxActionComponent.broadcast(AjaxActionComponent.java:55)
        at org.ajax4jsf.component.AjaxViewRoot.processEvents(AjaxViewRoot.java:317)
        at org.ajax4jsf.component.AjaxViewRoot.broadcastEvents(AjaxViewRoot.java:292)
        at org.ajax4jsf.component.AjaxViewRoot.processPhase(AjaxViewRoot.java:249)
        at org.ajax4jsf.component.AjaxViewRoot.processApplication(AjaxViewRoot.java:462)
        at com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:97)
        at com.sun.faces.lifecycle.LifecycleImpl.phase(LifecycleImpl.java:251)
        at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:117)
        at javax.faces.webapp.FacesServlet.service(FacesServlet.java:244)
        at org.apache.catalina.core.ApplicationFilterChain.servletService(ApplicationFilterChain.java:411)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:317)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:198)
        at org.ajax4jsf.webapp.BaseXMLFilter.doXmlFilter(BaseXMLFilter.java:154)
        at org.ajax4jsf.webapp.BaseFilter.handleRequest(BaseFilter.java:260)
        at org.ajax4jsf.webapp.BaseFilter.processUploadsAndHandleRequest(BaseFilter.java:366)
        at org.ajax4jsf.webapp.BaseFilter.doFilter(BaseFilter.java:493)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:230)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:198)
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:288)
        at org.apache.catalina.core.StandardContextValve.invokeInternal(StandardContextValve.java:271)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:202)
        at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:632)
        at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:577)
        at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:94)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:206)
        at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:632)
        at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:577)
        at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:571)
        at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:1080)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:150)
        at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:632)
        at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:577)
        at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:571)
        at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:1080)
        at org.apache.coyote.tomcat5.CoyoteAdapter.service(CoyoteAdapter.java:272)
        at com.sun.enterprise.web.connector.grizzly.DefaultProcessorTask.invokeAdapter(DefaultProcessorTask.java:637)
        at com.sun.enterprise.web.connector.grizzly.DefaultProcessorTask.doProcess(DefaultProcessorTask.java:568)
        at com.sun.enterprise.web.connector.grizzly.DefaultProcessorTask.process(DefaultProcessorTask.java:813)
        at com.sun.enterprise.web.connector.grizzly.DefaultReadTask.executeProcessorTask(DefaultReadTask.java:341)
        at com.sun.enterprise.web.connector.grizzly.DefaultReadTask.doTask(DefaultReadTask.java:263)
        at com.sun.enterprise.web.connector.grizzly.DefaultReadTask.doTask(DefaultReadTask.java:214)
        at com.sun.enterprise.web.portunif.PortUnificationPipeline$PUTask.doTask(PortUnificationPipeline.java:380)
        at com.sun.enterprise.web.connector.grizzly.TaskBase.run(TaskBase.java:265)
        at com.sun.enterprise.web.connector.grizzly.ssl.SSLWorkerThread.run(SSLWorkerThread.java:106)
org.hibernate.SessionException: Session is closed!
        at org.hibernate.impl.AbstractSessionImpl.errorIfClosed(AbstractSessionImpl.java:49)
        at org.hibernate.impl.SessionImpl.getBatcher(SessionImpl.java:260)
        at org.hibernate.loader.Loader.getResultSet(Loader.java:1801)
        at org.hibernate.loader.Loader.doQuery(Loader.java:674)
        at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:236)
        at org.hibernate.loader.Loader.doList(Loader.java:2220)
        at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2104)
        at org.hibernate.loader.Loader.list(Loader.java:2099)
        at org.hibernate.loader.criteria.CriteriaLoader.list(CriteriaLoader.java:94)
        at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1569)
        at org.hibernate.impl.CriteriaImpl.list(CriteriaImpl.java:283)
        at br.com.modelo.boi.BoiDAO.getBoiUnico(BoiDAO.java:42)
        at br.com.controle.ControleThreadLeituraArquivoServidor.lerArquivoB(ControleThreadLeituraArquivoServidor.java:470)
        at br.com.controle.ControleThreadLeituraArquivoServidor.run(ControleThreadLeituraArquivoServidor.java:109)

Seu eu não faço nenhuma outra ação durante a leitura dos arquivos não acontece nenhuma exception. Acho que ele está usando a mesma session do hibernate para fazer qualquer consulta, mas eu configurei o pool C3P0 da seguinte maneira:

    <!--  Propriedades do Pool de Conexões do C3P0 -->
        <property name="hibernate.c3p0.min_size">30</property>
        <property name="hibernate.c3p0.max_size">60</property>
        <property name="hibernate.c3p0.timeout">300</property>
        <property name="hibernate.c3p0.max_statements">50</property>
        <property name="hibernate.c3p0.idle_test_period">1000</property>
        <property name="hibernate.c3p0.acquire_increment">2</property>

Mas a impressão que dá é que não está funcionando.

Alguém pode me dar uma idéia de como resolver esse problema?

Obrigado desde já!

O problema não está na configuração do pool, provavelmente você deve estar tentando executar uam operaào na sessào já fechada.

Rafael, o que eu percebi, e aparentemente é o problema, é que quando coicidi de a minha Thread abrir a conexão para salvar no banco e, ao mesmo tempo, eu logar na aplicação(isso implica em abrir uma sessão para verificar o usuario e logo depois fechar) aconteceu que a sessão que estava aberta para salvar a linha do arquivo que a thread está lendo é fechada tb, como se fosse a mesma. E isso não era pra acontecer usando-se o pool de conexões certo?

Por isso pensei que o problema pudesse ser da configuração do C3P0… ainda estou sem resolver o problema e tentando algumas outras soluções para isso…

se tiver mais alguma sugestão será bem vinda… abraços

Não necessariamente. O pool só vai controlar as aberturas de conexões com o banco de dados, e você está interagindo com uma camada acima/anterior, que é a Sessão do Hibernate.
Pelo cenário que você falou, parece é que não está gerenciando as transações corretamente. Uma requisição não deveria interferir em outra Sessão além da sua.
Como está obtendo as sessões do Hibernate? Pode ser este o problema.

As sessões são adquiridas no meu HibernateFactory normalmente:

factory = cfg.buildSessionFactory();
session = factory.openSession();

As configurações estao corretas, pois funcionavam antes e funcionam em outros projetos aqui da empresa. Somente esse usa essa Thread de leitura simultaneamente com a aplicação.

Eu abro a sessão nesse método:

       public static Criteria getCriteria(Class c) throws HibernateException {
		Criteria criteria = null;
		try {
			log.debug("Abrindo sessão do banco de dados...");
			session = HibernateFactory.getSessionFactory().openSession();
            		criteria = session.createCriteria(c);
		} catch (HibernateException e) {
			throw new HibernateException("Erro ao criar Criteria", e);
		}
		return criteria;
	}

E fecho as sessões em todos métodos dos meus DAOs, no finally como é recomendado.

cara se vc tah usando servlet container (tomcat) obrigatoriamente vai ter q usar um OSIV (OPEN SESSION IN VIEW) filter
se vc tah num ejb3 container(jboss) nao precisa abrir conexoes ou fechar, mas eh obrigatorio que vc carregue todas as associacoes que estao marcadas como LAZY = TRUE e que vao ser usadas no render da pagina

olha isso

http://guj.com.br/posts/list/15/133184.java#718146
valeu

Vitenho, dei uma olhada nos posts que vc me falou e acho que não é exatamente o que vai resolver meu problema, se eu entendi direito. Agora eu tenho uma noção maior do meu problema, vou tentar resumir.

Eu tenho uma aplicação e uma thread iniciada pelo servidor(Localmente é o glassfish, mas quando eu jogar pro online vai ser o tomcat)
Essa Thread faz muitos acessos ao banco, e será executada de 15 em 15 minutos. Ela lê arquivos de ± 2000 linhas, e salva cada uma delas no banco, além de fazer uma consulta antes para ligar as linhas na entidades corretas.

A minha estrutura do hinernate é a seguinte, tenho um HibernateFactory que cria uma sessão somente, no seguinte método:

public static void hibernateFactory() throws HibernateException {
        try {
            Configuration cfg = new AnnotationConfiguration().configure((new HibernateFactory()).getClass().getResource("/hibernate.cfg.xml"));
            Properties props = new Properties();

    		//Recupera dados do arquivo hibernate.properties
    		try {
    			FacesContext aFacesContext = FacesContext.getCurrentInstance();
    			ServletContext context = (ServletContext)aFacesContext.getExternalContext().getContext();
    			String path = context.getRealPath("/") + ARQUIVO_PROPERTIES_LINUX;

    	       	if(!System.getProperty("os.name").equals("Linux")){
    	       		path = context.getRealPath("/") + ARQUIVO_PROPERTIES_WINDOWS;
    	       	}

    			File file = new File(path);
    			props.load(new FileInputStream(file));
    		}
    		catch (IOException ex) {
    			ex.printStackTrace();
    		}

            log.debug("Abrindo sessão do banco de dados...");
            factory = cfg.buildSessionFactory();
            session = factory.openSession();
        } catch (HibernateException e) {
            log.error("Falha na abertura da sessão do banco de dados");
            e.printStackTrace();
            factory = null;
            throw e;
        }
    }

Esse método é estático e gera somente uma session do hibernate, ou seja, a thread e a aplicação usam dividem a mesma session do hibernate. O que eu preciso é que seja criado uma session somente para a thread, para que ela possa acessar o banco a hora que quiser, e não atrapalhe o acesso ao banco pela aplicação. Isso vai acontecer simultaneamente muitas vezes.

Uma solução é eu fazer com que a Thread seja uma aplicação separada, mas eu queria saber se tem alguma maneira de eu dedicar uma session a essa Thread, entendeu? Dai toda vez que a Thread fosse acessar o banco ela usaria sua propria conexão (pool de conexões) e sua própria session.

Se tiver alguma dica ficaria agradecido… .

De qualquer maneira obrigado pelo post… valeu

ja tentasse o quartz?
http://www.opensymphony.com/quartz/wikidocs/TutorialLesson1.html

valeu

Vitenho, dei uma olhada no quartz, mas o que ele faz é agendamento de eventos né? A parte de esperar os 15 minutos pra rodar novamente já ta pronta… fiz com os recursos da Thread mesmo, o método run tem um loop infinito com while(true) e tenho um sleep dentro para parar durante 15 minutos.

Até agora a melhor solução que eu achei é fazer uma outra aplicação para que essa leitura de arquivos seja feita. Eu posso fazer uma aplicação java mesmo, que não precisa do tomcat e talvez sobrecarregue menos o servidor. Ainda estou dando uma estudada nisso.

Valeu pelas dicas, abraço.

cara eu indiquei o quartz por que a gente usa aqui,

como nós temos jpa sem CMT aqui no trampo, cada JOB tipo vira um session filter

tipo assim:


public class JunicoJob implements Job {

	public void execute(JobExecutionContext arg0) throws JobExecutionException {
			LOGGER.debug("Started executing Job");

			try { 
                                //aqui vc abre a sessao
                               // aqui vc inicia a transaction
				FacturacaoManager facturacaoManager = new FacturacaoManager();
				facturacaoManager.geraFatura();
                                // aqui vc comita
			} catch (Exception e) {
				LOGGER.error("Unexpected error while exectuting work name F7Job", e);
				Mail.sendMessage("junicojon@gmail.co","exception nas facturas", e.getMessage() + "\n" + e.getCause() + "\n"
						+ Global.buildStackTrace(e.getStackTrace()), true);
                                //aqui vc tem que fazer rollback pois deu merda de certeza!
				throw new RuntimeException(e);
			} finally {
                                //aqui testa se a transaction tah alive, se estiver é por que deu merda

                                  if(transaction.isAlive()) transaction.rollback();
			}

			LOGGER.debug("Finished executing F84Job");
		}
	}

}

e nunca deu problemas de session ou conexao

flw