WW: Registrar tempo de execução de uma Action

9 respostas
jack_ganzha

Eu apanhando do inglês nos foruns do WW

Olá, estou trabalhando em um sistema onde a busca é um dos principais quesitos e então, agora, decimos mostrar para o usuario, como o google faz, quanto tempo uma determinada consulta levou para ser executada. Então implementei um interceptor assim:
public String intercept(ActionInvocation invocation) throws Exception {
    
    String name = getActionName(invocation);
 
    StopWatch watch = new StopWatch();
    watch.start(name);
 
    ActionContext context = ActionContext.getContext();
 
    String result = invocation.invoke();
 
    watch.stop();
 
    context.put("time", new Double(watch.getTotalTimeSeconds()));
 
    return result;
 
}
O problema é que o codigo após o invocation.invoke() é executado apenas depois que a JSP é completamente renderizada e colocar o valor do tempo no contexto da action não vai adiantar porque a JSP já foi completamente mostrada quando ele ficar disponivel no contexto.

Eu tentei colocar o tempo na session, mas passei a recuperar o tempo da requisição anterior, não da atual. Eu sei que servlet filters têm o mesmo comportamento, então, como vcs sugerem que eu implemente essa medida de tempo de maneira elegante?

valeuz...

9 Respostas

_fs

O WW já vem com um TimerInterceptor imbutido.

com.opensymphony.xwork.interceptor.TimerInterceptor

Nunca precisei usar, mas não custa nada dar uma olhadinha no source dele para ver como o danado faz :thumbup:

smota

Ops … perai!

O interceptor é sim processado antes do result, tanto é que você pode fazer interceptors para alterar o result retornado (por exemplo se o caboclo não estiver logado).

Acho que o jeito mais fácil ao invés de usar o contexto (que não tem muito a ver com as expressões usadas na view) seja usar a própria action ou colocar um outro objeto na pilha.

Usando a própria action crie uma interface public interface TimedAction { public void setExecutionTime(long time) }, crie uma super-classe para todas as actions que você queira cronometrar a execução, ou implemente a interface diretamente na classe em questão e mude seu interceptor pra algo comAction action = invocation.getAction(); ... if(action instanceof TimedAction) (TimedAction) action).setExecutionTime(watch.getTotalTimeSeconds()) e finalmente coloque um getExecutionTime() na action que quiser e use na view $executionTime (velocity)

jack_ganzha

Olá,

LIPE, o problema é que o TimerInterceptor apenas loga o tempo necessario, ele não deixa o valor disponivel para acessar a partir de uma view, por exemplo, que é justamente o que eu quero. Tanto que esse interceptor é usado geralmente apenas durante o desenvolvimento.

valeuz…

jack_ganzha
Samuel, parte do interceptor é executada antes da renderização ser feita e outra parte é executada *depois*. O codigo que fica após o invocation.invoke só é processado depois que a view é completamente mostrada. Fiz o seguinte teste: coloquei um System.out.println("HELLO!!!") no fim da minha jsp e o log gerado foi:
...
[INFO ][2005-03-02:02:20:51]= (LoggingInterceptor.java:63) - Starting execution
stack for action search
[DEBUG][2005-03-02:02:20:51]= (DefaultActionInvocation.java:288) - Executing act
ion method = findByText
[DEBUG][2005-03-02:02:20:52]= (ServletDispatcherResult.java:57) - Forwarding to
location result.jsp
 
 
HELLO!!!
 
 
[INFO ][2005-03-02:02:20:52]= (TimerInterceptor.java:74) - Processed action sear
ch in 875ms.
[INFO ][2005-03-02:02:20:52]= (LoggingInterceptor.java:63) - Finishing execution
 stack for action search
[DEBUG][2005-03-02:02:20:52]= (RegisterTimeInterceptor.java:66) - Time for actio
n [0.875].
Ou seja, não vai adiantar setar o tempo na action depois de mostrar a JSP porque meu intuito é mostrar o tempo *na jsp*.

valeuz...

_fs

Pera, você esta colocando esse código na JSP, mas queria que ele fosse executado antes de mandar para a JSP??

jack_ganzha

No minha JSP eu tenho apenas o seguinte:

<ww:property value="time" />

“time” eu gostaria de setar no interceptor que registra o tempo de execução da Action, mas preciso executar a action antes para poder registrar o tempo (Oohh!), só que a parte do interceptor que coloca o valor no contexto da action só executa depois que a JSP é completamente renderizada, então, o valor de time está vazio.

Eu tentei o que o Samuel sugeriu, mas sem sucesso.

valeuz…

smota

Fio, vou ficar te devendo uma explicação ultra-mega-maluca do porque essa parada acontece com seu teste, mas eu ([size=9]quase[/size]) garanto que todos os interceptors são executados antes dos results, essa é a idéia deles, interceptar a ação e agir sobre ela alterando o resultado [SGM05] :stuck_out_tongue:

Lembrando que existem AroundInterceptors e outras coisitas diferentes do simples Interceptor.

Que tem jeito de fazer usando o interceptor sem gambiarra (acho) tem, to sem um ambiente pra testar aqui … mas faça uma versão simples do seu e manda pra cá que nóis tenta de novo.

ehehe foi mal ficar saindo de fininho com os achos e quase mas faz um tempinho que nao faço nada interessante com o Webwork e posso estar meio perdido :wink:

smota

Yeahhhhhhhhh … tá vendo que dá?

Só acho que meu exemplo foi mais elegante do que colocar na session :mrgreen:

jack_ganzha
Samuel, veja ele coloca o greeting no contexto, *antes* disso:
String result = invocation.invoke();
No meu caso, como eu preciso registrar o tempo de execução da action incluindo os outros interceptors, eu preciso colocar o valor *depois* de chamar o invoke:
public String intercept(ActionInvocation invocation) throws Exception {
     
     String name = getActionName(invocation);
  
     StopWatch watch = new StopWatch();
     watch.start(name);
  
     ActionContext context = ActionContext.getContext();
  
     String result = invocation.invoke();
  
     // daqui para frente é executado depois que a JSP foi mostrada!
     // Serio... :-p
     watch.stop();
  
     context.put("time", new Double(watch.getTotalTimeSeconds()));
  
     return result;
  
 }
Esse interceptor está no topo da stack para poder registrar *todo* o tempo.

valeuz...

Criado 2 de março de 2005
Ultima resposta 2 de mar. de 2005
Respostas 9
Participantes 3