Mentawai + PostgreSQL + DI + Axis

blz… na verdade procurei a dependência na web e achei alguns releases do google e baixei algumas versões porém todas deram esse mesmo problema… mas to na briga ainda, de alguma forma ou de outra vou tentar resolver aí eu volto aqui…

valeu!

Consegui resolver o problema importando uma lib específica no projeto também, então ao todo para utilizar o pool de conexões BoneCP (tendo em vista já a importação da lib do mentawai-all) são as seguintes:

BoneCP
SLF4J
Google-Collect

agora minha briga é outra… como nunca usei Mentawai em nenhum projeto específico (somente para estudo), estou implementando um BeanSession para o PostgreSQL utilizando sequences de retorno tipo Long mas em algum lugar de SequenceType (não olhei o fonte ainda) existe um cast para Integer, estourando um ClassCastException, mas isso é assunto para outro tópico…

O que achei estranho é a presença deste erro no servidor na API do Google

Ago 09, 2012 6:37:47 PM com.google.common.base.internal.Finalizer cleanUp Grave: Error cleaning up after reference. java.lang.reflect.InvocationTargetException at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:601) at com.google.common.base.internal.Finalizer.cleanUp(Finalizer.java:154) at com.google.common.base.internal.Finalizer.run(Finalizer.java:127) Caused by: java.lang.NullPointerException at com.jolbox.bonecp.ConnectionPartition$1.finalizeReferent(ConnectionPartition.java:191) ... 6 more

De qualquer forma, como ainda estou trabalhando nesta integração, então ainda não está 100%, e pode estar faltando algum detalhe…

Como ainda não pude fazer o teste do inject manual na DAO e demonstrar a solução real do problema inicial, vou retirar o tópico de resolvido, mas qualquer avanço nesta integração vou postando aqui…
valeu!

Testei basicamente 2 pools de conexão, o BoneCP (depois de importar as libs necessárias) e o DBCP, ambos funcionaram normalmente com PostgreSQL, criando as conexões e utilizando as já criadas para as requisições… porém quando é feito hot undeploy da aplicação, as conexões continuam lá… esse era um problema que eu tinha quando implementava o pool diretamente no código, por isso tive que mudar o pool para o tomcat gerenciar, inclusive aqui tem o tópico onde resolvo o problema fazendo isso…

Utilizando o Mentawai, é necessário algum encerramento manual dessas conexões?

Outro detalhe que notei é a quantidade de memory leaks que a aplicação gera… aparentemente as classes carregadas (contendo classes do Axis e do Menabean) continuam em memória mesmo após o undeploy…

Ago 10, 2012 9:55:19 PM org.apache.catalina.loader.WebappClassLoader clearThreadLocalMap Grave: The web application [/deployer] created a ThreadLocal with key of type [org.apache.axis.utils.XMLUtils.ThreadLocalDocumentBuilder] (value [org.apache.axis.utils.XMLUtils$ThreadLocalDocumentBuilder@79d2af80]) and a value of type [com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl] (value [com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl@77003afb]) but failed to remove it when the web application was stopped. This is very likely to create a memory leak. Ago 10, 2012 9:55:19 PM org.apache.catalina.loader.WebappClassLoader clearThreadLocalMap Grave: The web application [/deployer] created a ThreadLocal with key of type [java.lang.ThreadLocal] (value [java.lang.ThreadLocal@302071c6]) and a value of type [server.database.SistemaDAOImpl] (value [server.database.SistemaDAOImpl@220d96d9]) but failed to remove it when the web application was stopped. This is very likely to create a memory leak. Ago 10, 2012 9:55:19 PM org.apache.catalina.loader.WebappClassLoader clearThreadLocalMap Grave: The web application [/deployer] created a ThreadLocal with key of type [java.lang.ThreadLocal] (value [java.lang.ThreadLocal@2a2a9206]) and a value of type [server.database.control.PostgreSQLBeanSession] (value [server.database.control.PostgreSQLBeanSession@50d8dd8a]) but failed to remove it when the web application was stopped. This is very likely to create a memory leak. Ago 10, 2012 9:55:19 PM org.apache.catalina.loader.WebappClassLoader clearThreadLocalMap Grave: The web application [/deployer] created a ThreadLocal with key of type [org.apache.axis.utils.XMLUtils.ThreadLocalDocumentBuilder] (value [org.apache.axis.utils.XMLUtils$ThreadLocalDocumentBuilder@79d2af80]) and a value of type [com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl] (value [com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl@4db8b87d]) but failed to remove it when the web application was stopped. This is very likely to create a memory leak. Ago 10, 2012 9:55:20 PM org.apache.catalina.loader.WebappClassLoader clearThreadLocalMap Grave: The web application [/deployer] created a ThreadLocal with key of type [java.lang.ThreadLocal] (value [java.lang.ThreadLocal@1a583e68]) and a value of type [org.mentabean.BeanManager] (value [org.mentabean.BeanManager@17692b5b]) but failed to remove it when the web application was stopped. This is very likely to create a memory leak. Ago 10, 2012 9:59:40 PM org.apache.catalina.startup.HostConfig deployWAR Informações: Deploying web application archive deployer.war
Acredito que ambos os problemas se relacionam, pois só pelo fato das conexões não serem removidas já é um fator considerável para o vazamento de memória…
Teria alguma solução para isso?

Filhão, se vc está usando o BoneCPConnectionHandler com o ConnectionFilter do Mentawai isso tudo já foi resolvido pra vc. Como vc está fazendo isso na mão, o que não recomendo pois esse problema já foi resolvido pelo framework, então vou te explicar.

O ConnectionHandler possui um método destroy que precisa ser chamado quando a aplicação sofre um redeploy ou quando ela é terminada para limpar as coisas direitinho.

Logo o BoneCPConnectionHandler implementa esse método destroy, que limpa e fecha o BoneCP.

Daí é o ConnectionFilter que chama esse carinha quando a aplicação está terminando.

Olha o código linkado acima para entender a coisa. Veja que o Controlador do Mentawai, que é um servlet, possui o método destroy(), que é chamado pelo web container quando a coisa está sendo restartada ou terminada. Daí esse cara chama o destroy de todos os filtros, inclusive do ConnectionFilter que por sua vez chama o destroy do BoneCPConnectionHandler.

Se usa o Mentawai de forma high-level, vc não tem que se preocupar com isso. Isso é feito pra vc. Se usar um outro framework qualquer que não seja FULL-STACK, então vc vai ter que perder um dia entendendo e fazendo isso funcionar.

Sei que no seu caso vc não está usando o Mentawai puro, então vai ter que quebrar a cabeça para entender como essas coisas conversam e se integram entre si. Espero ter te ajudado. Qualquer coisa pergunte mais.

Obrigado saoj pelas explicações e pela atenção…

Não sei se eu tinha deixado isso claro antes, mas estou tentando utilizar o Mentawai por completo (a minha ideia é fazer a injeção manual somente na classe de Web Service que chama a DAO, pois essa classe de serviço é instanciada no invoke do ws), no restante, estou utilizando o Mentawai (com a AppManager por enquanto sem mapeamento de Actions pelo fato de não ter interface web no momento)…

Levando em conta o que vc disse adicionei o load do filtro na AppManager

@Override public void loadFilters() { filter(new ConnectionFilter(getConnectionHandler())); };
as conexões realmente foram limpadas no undeploy, mas os memory leaks ainda persistem…

Com o tempo ainda vou pegar bem o jeito, mas pelo que eu já estudei (inclusive fiz o artigo final da matéria de Linguagem III da faculdade só sobre Mentawai) achei muito interessante a forma full-stack e programática que o framework trabalha, é por esses e outros motivos que estou tentando a implementação dele em nossos sistemas, porém integrado com WebService…

Mas como eu citei antes, pretendo utilizar o Mentawai como um todo e somente fazer a injeção manual da parte de WebService através do container do AppManager, e aí vou conseguir integrar numa boa a parte desktop e web sob as mesmas camadas e ambas utilizando Injeção de Dependências controladas pelo Mentawai.

Se vc olhar bem esse warning vai ver que tem haver com a ThreadLocal da JVM. Parece que VM que vc está utilizando exige que o o thread local seja LIMPADO via método remove(). Nem o Mentawai nem o Axis estão fazendo isso. Eu nunca vi esse erro nas minhas aplicações. Talvez isso tenha haver com a sua configuração de tomcat?

http://wiki.apache.org/tomcat/MemoryLeakProtection

Pois é, já tinha lido esse artigo da Apache sobre Memory Leaks, inclusive tentei já com as versões mais novas do Tomcat, mas sem sucesso… O Axis sei que deixa Memory Leaks ao undeploy, mas quando controlo o pool pelo tomcat, a quantidade de vazamentos diminui bastante (Nenhuma classe da aplicação em si fica em memória, apenas algumas do Axis). Já utilizando o Mentawai qualquer DAO invocada fica em memória após o undeploy da aplicação. Outro detalhe é que eu não crio explicitamente nenhuma ThreadLocal, inclusive tem um tópico onde discuto sobre esses memory leaks…

De qualquer forma, vou continuar estudando esse problema ao poucos até achar alguma solução que elimine ou diminua esses vazamentos…

Olhando o código do ConnectionFilter, vejo que ele LIMPA o thread local. Teria que olhar nos outros lugares do Mentawai para saber se ele está fazendo isso sempre.

Dá uma olhada no método afterConsequence:

http://websvn.mentaframework.org/filedetails.php?repname=Mentawai+Web+Framework&path=%2Ftrunk%2Fsrc%2Fmain%2Fjava%2Forg%2Fmentawai%2Ffilter%2FConnectionFilter.java

O MentaContainer tb está removendo:

http://websvn.mentaframework.org/filedetails.php?repname=MentaContainer&path=%2Ftrunk%2Fsrc%2Fmain%2Fjava%2Forg%2Fmentacontainer%2Fimpl%2FMentaContainer.java

O MentaBean não usa thread local.

Só não vai me dizer que o threadLocal.set(null) é diferente do threadLocal.remove(). :shock:

Ok… vou dar uma procurada mais a fundo pra ver o por quê desses vazamentos… Só uma coisa, é o MentaContainer o responsável por invocar as classes e fazer a DI certo? Conforme vc me passou ele tb limpa a ThreadLocal no clear, então é estranho uma classe DAO ficar em memória, se é o MentaContainer que tem controle sobre ela. Corrija-me se eu estiver falando bobagem…

Vou fazer mais uns testes chamando o clear explicitamente do container do AppManager e ver o que acontece…

[quote=erico_kl]Ok… vou dar uma procurada mais a fundo pra ver o por quê desses vazamentos… Só uma coisa, é o MentaContainer o responsável por invocar as classes e fazer a DI certo? Conforme vc me passou ele tb limpa a ThreadLocal no clear, então é estranho uma classe DAO ficar em memória, se é o MentaContainer que tem controle sobre ela. Corrija-me se eu estiver falando bobagem…

Vou fazer mais uns testes chamando o clear explicitamente do container do AppManager e ver o que acontece…[/quote]

Sim mais como eu falei o clear está dando threadLocal.set(null) ao invés do remove. Não sei se é a mesma coisa. Dá uma olhada no código fonte do menta container e depois me diz o que vc achou.

blz, coincidentemente eu estava olhando um artigo sobre ThreadLocal e memory leak e vi o seguinte:

e logo após:

[quote]An explicity destroy method should have been provided on ThreadLocal. In
JDK 1.5, a new method remove
has been added to ThreadLocal?s API to complete its lifecycle management.
Users can call the remove method and avoid such memory leaks.[/quote]
fonte: http://www.0xcafefeed.com/2004/06/of-non-static-threadlocals-and-memory

Vou dar mais uma olhada nos códigos do Container, como vc disse, e vou trocar os set(null) no clear para remove() pra ver no que dá…

[quote=erico_kl]blz, coincidentemente eu estava olhando um artigo sobre ThreadLocal e memory leak e vi o seguinte:

e logo após:

[quote]An explicity destroy method should have been provided on ThreadLocal. In
JDK 1.5, a new method remove
has been added to ThreadLocal?s API to complete its lifecycle management.
Users can call the remove method and avoid such memory leaks.[/quote]
fonte: http://www.0xcafefeed.com/2004/06/of-non-static-threadlocals-and-memory

Vou dar mais uma olhada nos códigos do Container, como vc disse, e vou trocar os set(null) no clear para remove() pra ver no que dá…[/quote]

Good find! Vou mudar todos os lugares no Mentawai, MentaBean, MentaContainer, MentaXXXX onde estou setando para null.

Fião: boa sacada. Eu não sabia desse detalhe do ThreadLocal. Agora sei. Thanks. :slight_smile:

Nova release do MentaContainer sem esse problema: 0.9.9

Nova release do Mentawai sem esse problema 2.5.3.

Pode baixar do Maven já.

Houve várias alterações no Mentawai, uma delas no ConnectionFilter => http://websvn.soliveirajr.com/diff.php?repname=Mentawai+Web+Framework&path=%2Ftrunk%2Fsrc%2Fmain%2Fjava%2Forg%2Fmentawai%2Ffilter%2FConnectionFilter.java&rev=288

Beleza cara…

Só vi agora o post, mas que bom que consegui ser útil em alguma coisa rsrs…

Vou baixar a nova versão para começar a lidar (provavelmente terei que fazer fora de hora), mas talvez não irei mais integrar com o Axis, e sim com o Apache CXF. Li alguns artigos comparativos e vi que o CXF além de trabalhar com SOAP pode integrar uma arquitetura REST… Me chamou atenção também a possibilidade de integrar com Spring, mas acho que não sou só eu que odeia XML pra tudo rsrs, por isso estou vendo a possibilidade de integrar o Apache CXF com o MentaContainer para IoC… mas ainda é só estudo…

saoj, você já trabalhou com algum framework pra implementação de WebServices em alguma aplicação sua (Axis, CXF, Jersey, JBossWS…)? Se sim, integrou com o Mentawai?

Abraço!

[quote=erico_kl]Beleza cara…

Só vi agora o post, mas que bom que consegui ser útil em alguma coisa rsrs…

Vou baixar a nova versão para começar a lidar (provavelmente terei que fazer fora de hora), mas talvez não irei mais integrar com o Axis, e sim com o Apache CXF. Li alguns artigos comparativos e vi que o CXF além de trabalhar com SOAP pode integrar uma arquitetura REST… Me chamou atenção também a possibilidade de integrar com Spring, mas acho que não sou só eu que odeia XML pra tudo rsrs, por isso estou vendo a possibilidade de integrar o Apache CXF com o MentaContainer para IoC… mas ainda é só estudo…

saoj, você já trabalhou com algum framework pra implementação de WebServices em alguma aplicação sua (Axis, CXF, Jersey, JBossWS…)? Se sim, integrou com o Mentawai?

Abraço![/quote]

Já trabalhei com SOAP => http://www.seducaotecnologica.com.br/tutorial-soa-passo-a-passo-1/

Mas não gosto. Faço web services em cima do Mentawai mesmo, sem me atrelar a um contrato de publicacao como o WSDL. Foi o que eu falei aqui:

Sem querer pedir demais mas você tem algum exemplo de como seria o funcionamento? Você implementa o lado servidor somente com Mentawai? E o cliente para consumir esse serviço pode ser desktop sem problemas?

Veja como o Mentawai suporta Ajax de forma bem simples e flexível => http://www.mentaframework.org/mtw/Page/Ajax/mentawai-ajax

Um web service nada mais é que uma requisição AJAX. SOAP e REST são especificações (ugh!) para PUBLICAR os web services para o mundo. Acho que um cliente qualquer pode dar um parse no WSDL para se preparar para falar com os seus web services. Naquele link lá você pode ver como um cliente Ruby pode parsear o WSDL e começar a falar com os seus web services sem problemas.

Mas ao invés de suportar o WSDL eu posso chegar pra vc e falar assim:

Hey, chama essa URL aqui passando o ID de um usuário que vc vai receber um JSON com todas as informações dele:

https://ws.mycompany.com/mtw/User

Como parametros POST vc pode passar: (acho que é mais seguro do que passar isso via GET - agora fiquei na dúvida se o https encrypta os parametros na URL)

  • login
  • password
  • id do usuário que vc quer

Aí vc vai receber um JSON de volta com todas as informações do seu usuário.

Única pergunta que ficou na minha cabeça é se tem uma maneira de compartilhar o objeto USER no lado do servidor (web services) com os clientes. Acho que isso vc pode fazer e prover um jar para os consumidores do seu web service.

Blz…

Vou seguir os passos do site que você citou, mas o outro site (https://ws.mycompany.com/mtw/User) está fora…

O que faço hoje é serializar todas as informações que vão para o WS (pois somente quem vai consumir esse web service é o cliente desktop que a gente mesmo desenvolve), o sistema todo é desktop e faz as requisições nesses WebServices enviando os objetos compactados e serializados para o (atualmente) Axis. Já no lado server eu simplesmente desserializo esse objeto e faço as operações de persistência e retorno outro objeto serializado… Basicamente é assim que tenho hoje…

A performance do sistema fica bem interessante compactando e mandando os objetos todos como byte[]… quero ver se consigo transmitir de forma simples os objetos fazendo essa serialização neste novo conceito…

[quote=saoj]Nuca vi esse erro. Eu uso Maven e importo no maven. Nunca usei o mentawai-all.jar.

http://www.mentaframework.org/mtw/Page/RefApp/mentawai-aplicacao-de-referencia[/quote]

O mentawai-all.jar foi consertado para incluir todas as classes. Antes não estava…

opa, beleza…

atualizando o projeto aqui…

abraço!