Você tem que criar um objeto do tipo Throwable e através deste objeto acessar o stack de chamada de métodos. Com isto você consegue saber qual foi o método que o chamou… Que eu saiba esta é a única forma de sefazer isto em Java.
Neste caso talvez a melhor opção seja fazer a modelagem e passar algum parâmetro que permita a identificação de onde aquele método foi chamado.
Guerr
Vamos lá!! O problema está ficando mais complicado…
Como não dá para acessar de onde chamou o método e nem passar um parâmetro para o método, uma sugestão seria você colocar alguma coisa em um ThreadLocal e acessar de dentro do método… Se você criar um proxy antes de chamar o método (não dá para ser dinâmico por causa da JDK 1.3) dá para você colocar nesta variável ThreadLocal o método que você vai chamar. Se você quiser criar o proxy dinamicamente e quiser aprender uma parada hardcore, você pode fazer isto utilizando a CGLIB.
Resolve o problema?
Guerr
Valeu!!! Heheheh!!!
Quando você descobrir como o Log4J faz você posta aí que eu fiquei curioso… E vai ser mais uma coisa na manga para soluções mirabolantes como esta!!!
T
thingol
Atenção: o código abaixo é só um esboço - há um monte de StringWriters/Readers e PrintWriters que devem ser fechados.
importjava.io.*;classTesteThrowable{publicvoidfuncao3(){Throwableth=newThrowable();StringWritersw=newStringWriter();PrintWriterpw=newPrintWriter(sw);th.printStackTrace(pw);System.out.println("*** O stack trace gerado artificialmente ***");System.out.println(sw);BufferedReaderbr=newBufferedReader(newStringReader(sw.toString()));try{System.out.println("*** Quem me chamou? ***");StringquemMeChamou;br.readLine();// pulo a primeira linha que é lixobr.readLine();// pulo a segunda que é esta própria rotinaquemMeChamou=br.readLine();System.out.println(quemMeChamou);// o resultado deve ser "funcao2"}catch(IOExceptionex){}}publicvoidfuncao2(){funcao3();}publicvoidfuncao1(){funcao2();}publicstaticvoidmain(String[]args){TesteThrowablett=newTesteThrowable();tt.funcao1();}}
Guerr
Caramba!!! Cada manobra hein!!! Vai dar um trabalhinho, mas eu acho que o caminho é este…
T
thingol
O .NET (pelo menos na versão 1.1) tem uma coisa semelhante ao getStackTraceElement(), só que ele faz uma coisa muito feia - se a rotina for considerada passível de ser posta “inline”, o stack trace começa a “pular” níveis de rotinas - e então, muitas vezes, você não consegue saber exatamente “quem me chamou”.
Em contraste, mesmo que o JIT do Java faça a mesma otimização (“pular rotinas”), o stack trace sempre é correto (acho que é por isso que o tratamento de exceptions é relativamente lento em Java, já que tem de ser feita uma “desotimização” em tempo de execução).
Eu tive esse problema quando tive de fazer algo parecido com isso em .NET - argh!
cv1
Ja deu uma olhada em Thread.currentThread().getStackTrace()?
como faço para saber, runtime, qual metodo/construtor invocou um suposto método alvo…
Ex:
class A{
StringgetB(){
returnnewB().get(); // aqui retornaria os valores da class A e método getB
}
}
class B(){
Stringget(){
return"Método chamado a partir da classe “++”, método "+;
}
}
seufagner
Não é a maneira mais elegante (se bem que a única) nem a “semanticamente correta”, mas rola mesmo…
valeu Guerra!
seufagner
o ambiente é muito restrito e nao vejo necessidade em acoplar um framework aop para o caso… adicionaria complexidade desnecessaria, ja que é um cenario unico e isolado, dentro do sistema, que dificilmente vai ser modificado…
valeu a força furutani
seufagner
funciona… a partir do 1.4… o weblogic daqui roda 1.3 rsrs
ouvi falar que o log4j utiliza algo parecido, analisando seu fonte, e roda no 1.3… vou dar mais uma investigada, posto a solução aqui depois
seufagner
o caso é: uma manutenção no framework proprietário. a intenção Guerra é realmente eliminar a parametrizacao. ao executar um execute(), executeUpdate() etc… montar o comentario para a sentenca sql “por baixo dos panos”… isto mostra-se necessário devido ao fato da equipe ser relativamente grande e com muita gente inexperiente, esquecida ou adjetivos semelhantes… rsrs…
só para atenuar, o sistema é grande, com muito jsp “macarrônico” acessando classes diretamente ou não… ou seja, pode ter impactos desagradáveis, claro, qualquer tipo de remodelagem…
o gostoso da nossa área é justamente isso… os desafios, não só codificar ou utilizar o framework mais high-tec… rs
seufagner
nao da pra rebuscar nao… embora threadlocal tenha bom desempenho por usar codigo hash o lance de utiliza-la vai ficar custoso, tendo em vista que todas as classes de acesso a dados terao q ter seu proxy… mesmo que pudesse usar proxy dinamico, ainda sim ia ficar custoso, acredito. ja usei o cglib num projeto, o garoto é poderoso… mas nao tem no meu classpath e ninguem quer colocar ele por aqui nao, é uma burocracia do caralho acrescentar um lib q seja… rsrs… mas ficou bonita essa tua ideia, gostei mesmo Guerra…
em tempo, to olhando a api do log4j pra sentir a solucao dos caras… exatamente a classe PatternLayout que implementa o %C2% na hora de formatar o Layout que o cara configurou… %C2% mostra a classe e o metodo, mesmo na 1.3… to curioso pra ver como o cara implementou isso…
seufagner
o lance é que assim vai sempre supor que está na terceira linha… nem sempre será assim… consegui emular aqui uma situação que retornou null… o lance é por aí mesmo, similar à utilizada pelo Log4J, porém a jogada de como manipular o string correspondente ao stack é diferente… valeu thingol!
matando a curiosidade (minha inclusive), no Log4J, quem diria, eles fazem um jogo de lastIndexOf, substring e tosqueiras a parte! rsrsrs… tudo pela compatibilidade com o 1.3 q ainda nao tinha metodo algum que devolvesse o stack… (vide classe LocationInfo)
a partir da 1.4 ja se encontra o getStackTraceElement() que retorna um array de objetos de StackTraceElement… uma beleza!
[]s pessoal!
seufagner
aqui usam 1.3 e nao vao mudar nem tao cedo por varias questoes, inclusive o medo que quiçá surjam incompatibilidades aos artefatos. e, mais ainda, porque a versao do weblogic daqui so roda na 1.3… logo é sempre um “se vira nos 30” rsrs