Ajuda com Interceptor no VRaptor 3 [RESOLVIDO]

19 respostas
D

Boa tarde,

estou com um problema no VRaptor que está difícil de identificar.

O meu tomcat está lançando essa exceção na linha final do interceptor ->stack.next( method, resourceInstance );
O interceptor é simples, só verifica se perdeu sessão.

Vários métodos interceptados tem dado essa exceção, e a maioria (se não todos) é método que retorna json para o página.
Eu retorno json usando result.use( Results.json( ) ).from( objeto ).serialize( );
e o json vai para a página normal, mas a exceção sempre solta.

java.lang.IllegalStateException: Cannot forward after response has been committed

at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:312)

at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:302)

at br.com.caelum.vraptor.view.DefaultPageResult.defaultView(DefaultPageResult.java:67)

at br.com.caelum.vraptor.interceptor.ForwardToDefaultViewInterceptor.intercept(ForwardToDefaultViewInterceptor.java:60)

at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54)

at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54)

at br.com.caelum.vraptor.core.LazyInterceptorHandler.execute(LazyInterceptorHandler.java:61)

at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54)

at br.com.caelum.vraptor.core.LazyInterceptorHandler.execute(LazyInterceptorHandler.java:61)

at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54)

at br.com.caelum.vraptor.interceptor.ExecuteMethodInterceptor.intercept(ExecuteMethodInterceptor.java:85)

at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54)

at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54)

at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:56)

at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54)

at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:56)

at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54)

at br.com.caelum.vraptor.core.LazyInterceptorHandler.execute(LazyInterceptorHandler.java:61)

at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54)

at br.edeploy.gol.webcheckin.interceptor.SessionInterceptor.intercept(SessionInterceptor.java:101)

at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54)

at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54)

at br.com.caelum.vraptor.interceptor.ExceptionHandlerInterceptor.intercept(ExceptionHandlerInterceptor.java:71)

at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54)

at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54)

at br.com.caelum.vraptor.interceptor.FlashInterceptor.intercept(FlashInterceptor.java:83)

at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54)

at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54)

at br.com.caelum.vraptor.interceptor.InstantiateInterceptor.intercept(InstantiateInterceptor.java:48)

at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54)

at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54)

at br.com.caelum.vraptor.interceptor.ParametersInstantiatorInterceptor.intercept(ParametersInstantiatorInterceptor.java:87)

at br.com.caelum.vraptor.core.LazyInterceptorHandler.execute(LazyInterceptorHandler.java:59)

at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54)

at br.com.caelum.vraptor.interceptor.ResourceLookupInterceptor.intercept(ResourceLookupInterceptor.java:69)

at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54)

at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54)

at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:56)

at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54)

at br.com.caelum.vraptor.core.EnhancedRequestExecution.execute(EnhancedRequestExecution.java:44)

at br.com.caelum.vraptor.VRaptor$1.insideRequest(VRaptor.java:92)

at br.com.caelum.vraptor.ioc.spring.SpringProvider.provideForRequest(SpringProvider.java:58)

at br.com.caelum.vraptor.VRaptor.doFilter(VRaptor.java:89)

at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)

at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)

at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)

at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)

at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)

at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)

at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:555)

at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)

at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)

at org.apache.jk.server.JkCoyoteHandler.invoke(JkCoyoteHandler.java:190)

at org.apache.jk.common.HandlerRequest.invoke(HandlerRequest.java:291)

at org.apache.jk.common.ChannelSocket.invoke(ChannelSocket.java:769)

at org.apache.jk.common.ChannelSocket.processConnection(ChannelSocket.java:698)

at org.apache.jk.common.ChannelSocket$SocketConnection.runIt(ChannelSocket.java:891)

at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:690)

at java.lang.Thread.run(Thread.java:619)

Valeu…

19 Respostas

L

o problema é que, provavelmente, vc tá chamando o stack.next mesmo que o cara perdeu a sessão. Nesse caso, o cara já provavelmente renderizou o jsp, daí não adianta mais usar o result, pois dá esse erro mencionado (o response já foi comitado).

é só não chamar o stack.next em caso de erro.

D

O problema é que eu não estou perdendo sessão.
Eu chamo uma página e quando ela abre ele acessa o json do meu método getData(). E dá tudo certo, o stack.next funciona, a função executa, retorna o json para a página, ele volta e cai nesse catch.

try{
				stack.next( method, resourceInstance );
			}catch (Exception e) {
				System.out.println("Method Access Start: " + method.getMethod( ).getName( ) );
				if( methodInfo != null && methodInfo.getParameters() != null ){
					for( Object o : methodInfo.getParameters() )
						if( o != null ){
							System.out.println( o.toString() );
						}
				}
				e.printStackTrace();
				System.out.println("Method Access End:" + method.getMethod( ).getName( ) );
			}
L

vc está gerando o json em um interceptor, depois do stack.next()?

D

Não, também não… só no método mesmo que eu retorno json. O interessante é que funciona, e solta exceção.

L

tem algum forward acontecendo no meio do caminho?

o código do sessionInterceptor chama o result.use alguma coisa?

D

Então Lucas, tem um result.use no interceptor, mas ele não chama quando acontece o erro.

Tem uma coisa que eu não falei que o método getData que tem um retorno de json é chamado 2 vezes concorrentemente quando a página carrega.
E nem sempre as 2 chamadas causam a exception, mas pelo menos uma

package br.edeploy.gol.web.interceptor;

import java.rmi.RemoteException;
import java.util.Arrays;

import br.com.caelum.vraptor.InterceptionException;
import br.com.caelum.vraptor.Intercepts;
import br.com.caelum.vraptor.Result;
import br.com.caelum.vraptor.core.InterceptorStack;
import br.com.caelum.vraptor.core.MethodInfo;
import br.com.caelum.vraptor.interceptor.Interceptor;
import br.com.caelum.vraptor.resource.ResourceMethod;
import br.com.caelum.vraptor.view.Results;
import br.edeploy.gol.web.bean.Session;
import br.edeploy.gol.web.controller.WebController;

@Intercepts
public class SessionInterceptor implements Interceptor {
	
	private final Session session;
	private final Result result;
	private final MethodInfo methodInfo;
	
	public SessionInterceptor( Session session, Result result, MethodInfo methodInfo ) {
		this.session = session;
		this.result = result;
		this.methodInfo = methodInfo;
	}
	
	@SuppressWarnings( "unchecked" )
	@Override
	public boolean accepts( ResourceMethod method ) {
		if ( Arrays.asList( WebController.class ).contains( method.getMethod( ).getDeclaringClass( ) ) ) {
			return true;
		}
		return false;
	}
	
	@Override
	public void intercept( InterceptorStack stack, ResourceMethod method,
			Object resourceInstance ) throws InterceptionException {
		
		boolean b = false;
		if ( session.isSessionLost( ) ) {
			result.include( "errorMessage", "error.sessionExpired" );
					
                        //json methods	
			if ( method.getMethod( ).getName( ).equals( "sendSMS" ) ||
					method.getMethod( ).getName( ).equals( "getData" ) ||
					method.getMethod( ).getName( ).equals( "saveDataOnSession" ) ) {
				result.use( Results.json( ) ).from( "Erro sessao." ).serialize( );
			}
			else {
				
				try {
					result.redirectTo( WebController.class ).initialize( );
					return;
				}
				catch ( RemoteException e ) {
					// TODO Auto-generated catch block
					e.printStackTrace( );
				}
				
			}
		}
		else {
			try{
				stack.next( method, resourceInstance );
				return;
			}catch (Exception e) {
                                //Funciona e cai aqui
                                //print method name and stacktrace
				System.out.println("Method Access Start: " + method.getMethod( ).getName( ) );
				if( methodInfo != null && methodInfo.getParameters() != null ){
					for( Object o : methodInfo.getParameters() )
						if( o != null ){
							System.out.println( o.toString() );
						}
				}
				e.printStackTrace();
				System.out.println("Method Access End:" + method.getMethod( ).getName( ) );
				return;
			}
		}
		
	}
	
}

o método para chamar o json na jsp é esse

$.ajax(				

				{url:"getData?contadorAjax="+contador, dataType:'json', timeout: 100000, scriptCharset: 'ISO-8859-1', 
					success: function(data) 
					{
                                                   //code
                                         }
                                 }
    );
L

o erro acontece qdo dá o “Erro sessao.”?

posta por favor o código do getData.

D

Não é no “erro sessão”, ele chega até o stack.next, redireciona para o getData, envia o json para a página, e dá o erro.
o getData é simbólico…

@Path( "/getData" )
	public void getData() {

                result.use( Results.json() ).from( "lall lal l al al al al a", "msg" ).serialize( );
		return;
	}

Mas não afeta a aplicação essas exceções, mas eu queria saber porque acontece isso… e fica poluindo o log do tomcat

Se não o jeito vai ser deixar ficar lançando…

valeu Lucas…

D

Então Lucas, como eu fazia requisições concorrentes para a mesma função, eu resolvi fazer sincrono o ajax com o async:false, e resolveu.
Mas deveria funcionar com mais requisições, não é?

L

deveria sim…

de qqer forma é estranho estar acontecendo isso, pois esse erro acontece qdo vc faz um forward depois de ter usado o response pra fazer alguma coisa.

vc está usando algum controller ou interceptor @SessionScoped?

D

Também não :confused:

só a session mesmo é @Component @SessionScoped.

L

e vc usa o result ou validator ou algo do tipo dentro dela?

D

O lucas, desculpa por não responder…

eu tenho um result no Session. Mas uso só como variável, get set… não uso include ou use dentro da session…
Eu estancio um Result result no controller e atribuo ao meu ourResult da session no construtor… para guardar valores do include somente.

e não tenho validator na session.

L

pode postar um pedaço do código que vc está usando nesse @SessionScoped pra eu tentar ver o que está acontecendo, por favor?

D

Esse é parte do código da sessão. Eu tenho um result.

@Component
@SessionScoped
public class Session implements Serializable {
  private OurResult ourResult = new OurResult( );
  
  public void setOurResult( OurResult ourResult ) {
		this.ourResult = ourResult;
	}
	
	public OurResult getOurResult( ) {
		return ourResult;
	}
}

Agora o código do OurResult

public class OurResult implements Result, Serializable{
	
	private static final long serialVersionUID = -8069213645818587883L;
	
	private Result result;
	private HashMap<String, Object> refresh = new HashMap<String, Object>();
	
	
	public void setResult(Result result){
		this.result = result;
		
	}
	
	public void clear(){
		refresh.clear();
		
	}
	
	
	public void updateHashMap(String key, Object ob){
		
		refresh.put(key, ob);
		
	}
	
	public void doRefresh(String language, Session session){
		
		if(language.equals("ENG"))
			session.setLanguage("EN_US");
		else if(language.equals("BRA"))
			session.setLanguage("PT_BR");
		else if(language.equals("ESP"))
			session.setLanguage("ES_ES");
		
				
		for( String key : refresh.keySet()){
						
			result.include(key, refresh.get(key));
		}
		
		result.include("language", session.getLanguage());
		
	}
	
	public void forwardTo(String arg0) {
		result.forwardTo(arg0);
		
	}

	
	public <T> T forwardTo(Class<T> arg0) {
		return result.forwardTo(arg0);
	}

	@Override
	public <T> T forwardTo(T arg0) {
		return result.forwardTo(arg0);
	}

	@Override
	public Result include(Object arg0) {		
		return result.include(arg0);
	}

	@Override
	public Result include(String arg0, Object arg1) {
		refresh.put(arg0, arg1);
		return result.include(arg0, arg1);
	}

	@Override
	public Map<String, Object> included() {
		return result.included();
	}

	@Override
	public void notFound() {
		result.notFound();
		
	}

	@Override
	public void nothing() {
		result.nothing();
		
	}

	@Override
	public <T> T of(Class<T> arg0) {
		return result.of(arg0);
	}

	@Override
	public <T> T of(T arg0) {
		return result.of(arg0);
	}

	@Override
	public Result on(Class<? extends Exception> arg0) {
		return result.on(arg0);
	}

	@Override
	public void permanentlyRedirectTo(String arg0) {
		result.permanentlyRedirectTo(arg0);
		
	}

	@Override
	public <T> T permanentlyRedirectTo(Class<T> arg0) {
		return result.permanentlyRedirectTo(arg0);
	}

	@Override
	public <T> T permanentlyRedirectTo(T arg0) {
		return result.permanentlyRedirectTo(arg0);
	}

	@Override
	public void redirectTo(String arg0) {
		result.redirectTo(arg0);
		
	}

	@Override
	public <T> T redirectTo(Class<T> arg0) {
		return result.redirectTo(arg0);
	}

	@Override
	public <T> T redirectTo(T arg0) {
		return result.redirectTo(arg0);
	}

	@Override
	public <T extends View> T use(Class<T> arg0) {
		return result.use(arg0);
	}

	@Override
	public boolean used() {
		return result.used();
	}
	
	
	

}

Dai no inicio do controler eu já seto

session.getOurResult( ).setResult( result );
this.result = session.getOurResult( );

valeu

L

esse OurResult é um componente? não deveria…

em todo caso, com esse código não funciona?

o controller é RequestScoped? (se não tiver nenhuma anotação de escopo, esse é o padrão)

D

O OurResult não tem anotação.

O controller é @Resource, pode tirar?

então…poderia deixar assim, mas funcionar, tudo funciona… o problema é que o stack next ainda lança exceção.

L

não, o controller precisa ser @Resource.

tem algum lugar do seu código que vc faz o session.getOurResult.getResult() e faz alguma coisa com ele?

o que pode estar acontecendo é que vc está usando o result da requisição errada (principalmente se acontecem requisições simultâneas do mesmo usuário).

Você está usando o spring ou o guice como container? (só ver pelos jars).

Se vc puder usar o guice, vc pode receber no construtor um Provider, que sempre pega o result da requisição certa.

D

RESOLVIDO!!! UFA!

era isso mesmo, o problema que estava dando é que eu chamada 2 vezes o mesmo método, simultâneo. Dai os 2 setavam o result na session e um acabava usando o result do outro. Ai lançava a exceção mas a aplicação não quebra. E por isso também que lançava uma exceção para 2 requisições. Agora tenho que ter certeza que o result seja o da requisição certa. Vou dar uma olhada no guice porque atualmente eu uso o spring.

Valeu lucas

Criado 14 de fevereiro de 2012
Ultima resposta 27 de fev. de 2012
Respostas 19
Participantes 2