VRaptor 3: upload de arquivo

Pessoal

Estou tendo problema para fazer upload d earquivos com o VRaptor.

Arquivos menores estão subindo sem problema nenhum. O problema começa quando tento subir um arquivo maior (no caso, testando com doc de 5 MB).

Criei uma classe para permitir arquivos grandes, conforme documentação do VRaptor:

public class UploadConfig extends DefaultMultipartConfig {
	public long getSizeLimit() {
        return 30 * 1024 * 1024; // 50MB
    }
}

Mesmo assim não sobem arquivos grandes.

Estava dando erro de ClassNotFoundException, org.hamcrest.Description. Coloquei o jar hamcrest-all no lib e parou esse eroo, mas ficou uma pergunta: porque arquivos menores não precisam e grandes precisariam desse jar?

Porém, passei a ter outro erro:

19/10/2010 14:19:29 org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet default threw exception
br.com.caelum.vraptor.InterceptionException: an exception was raised while executing resource method
	at br.com.caelum.vraptor.interceptor.ExecuteMethodInterceptor.intercept(ExecuteMethodInterceptor.java:86)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:65)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:56)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:65)
	at br.com.caelum.vraptor.interceptor.ParametersInstantiatorInterceptor.intercept(ParametersInstantiatorInterceptor.java:77)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:65)
	at br.com.caelum.vraptor.interceptor.InstantiateInterceptor.intercept(InstantiateInterceptor.java:42)
	at br.com.caelum.vraptor.core.InstantiatedInterceptorHandler.execute(InstantiatedInterceptorHandler.java:47)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:65)
	at gpo.util.interceptor.NoCacheInterceptor.intercept(NoCacheInterceptor.java:50)
	at br.com.caelum.vraptor.core.InstantiatedInterceptorHandler.execute(InstantiatedInterceptorHandler.java:47)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:65)
	at br.com.caelum.vraptor.util.hibernate.HibernateTransactionInterceptor.intercept(HibernateTransactionInterceptor.java:45)
	at br.com.caelum.vraptor.core.InstantiatedInterceptorHandler.execute(InstantiatedInterceptorHandler.java:47)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:65)
	at br.com.caelum.vraptor.interceptor.InterceptorListPriorToExecutionExtractor.intercept(InterceptorListPriorToExecutionExtractor.java:46)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:65)
	at br.com.caelum.vraptor.interceptor.FlashInterceptor.intercept(FlashInterceptor.java:81)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:65)
	at br.com.caelum.vraptor.interceptor.ResourceLookupInterceptor.intercept(ResourceLookupInterceptor.java:67)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:65)
	at br.com.caelum.vraptor.interceptor.multipart.MultipartInterceptor.intercept(MultipartInterceptor.java:96)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:65)
	at br.com.caelum.vraptor.core.DefaultRequestExecution.execute(DefaultRequestExecution.java:70)
	at br.com.caelum.vraptor.VRaptor$1.insideRequest(VRaptor.java:92)
	at br.com.caelum.vraptor.ioc.spring.SpringProvider.provideForRequest(SpringProvider.java:56)
	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.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
	at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:852)
	at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)
	at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
	at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.NullPointerException
	at gpo.controller.ProjetoController.uploadArquivo(ProjetoController.java:435)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	at java.lang.reflect.Method.invoke(Unknown Source)
	at br.com.caelum.vraptor.interceptor.ExecuteMethodInterceptor.intercept(ExecuteMethodInterceptor.java:57)
	... 44 more

Ta dando NullPointerException em um local que não poderia, pois com arquivos menores não dá. No código abaixo sinalizo a linha da 435, apontada na Exception.

        @Path("/projetoUploadArquivo")
	@Acesso(restricao=Restricao.RESTRITO)
	public void uploadArquivo(Projeto projeto, UploadedFile arquivo){
		projeto = this.daoFactory.getProjetoDao().procura(projeto.getId()); //LINHA DO NULL POINTER EXCEPTION
		
		result.include("projeto", projeto);
		
		String realPath = request.getRealPath("WEB-INF/arquivos");  
		SimpleDateFormat df = new SimpleDateFormat("dd.MM.yy-HH.mm.ss");
		String nomeDoArquivo = df.format(new Date())+"_"+arquivo.getFileName();
		
		File destino = new File(new File(realPath), nomeDoArquivo);  
		try {
			IOUtils.copyLarge(arquivo.getFile(), new FileOutputStream(destino));
		} catch (Exception e) {
			logger.fatal("Exception no upload do arquivo: "+e.getMessage());
			e.printStackTrace();
			result.include("mensagem", "Houve um erro ao realziar o upload do arquivo.");
			result.redirectTo(ProjetoController.class).detalhamentoProjeto(projeto);
		} 
		
		projeto.getArquivos().add(nomeDoArquivo);
		this.daoFactory.getProjetoDao().atualiza(projeto);
		result.include("mensagem", "Upload de arquivo realizado com sucesso.");
		result.redirectTo(ProjetoController.class).detalhamentoProjeto(projeto);
	}

Se alguém puder me ajudar a resolver esse erro agradeço, e também esclarecer minha dúvida do hamcrest-all.jar.

Obrigado

Em algum lugar do seu código algum objeto está vindo nulo, então tem um null-pointer-exception aqui:

Caused by: java.lang.NullPointerException at gpo.controller.ProjetoController.uploadArquivo(ProjetoController.java:435)

garcia

Como eu disse, o formulário está mandando o objeto necessário, tanto que quando tento com arquivos menores, vai com sucesso.

Quando tento um arquivo maior que da esse erro.

Faça um debug nesse ponto aqui:

Veja quais desses caras é null.

Hmm, perae… qual o container que você está usando? Por acaso é Tomcat7?

Sim, é o Tomcat.

Tem algum limite imposto pelo Tomcat?

Como eu mostrei, acredito ter alterado o limite da API, mas do Tomcat desconheço.

Valew

[quote=paulohrl]Sim, é o Tomcat.

Tem algum limite imposto pelo Tomcat?

Como eu mostrei, acredito ter alterado o limite da API, mas do Tomcat desconheço.

Valew[/quote]

Qual versão? A 7?

O Vraptor não possui problema algum com o Tomcat, porém o Tomcat 7 possui problemas no upload, já que a versão 7 ainda é beta.

Tomcat 6

Não lembro quanto que é o limite padrão do vraptor, mas vc pode aumentar o tamanho limite do arquivo do upload, vc tem q sobreescrever assim:

 @Component  
 @ApplicationScoped  
 public class CustomMultipartConfig extends DefaultMultipartConfig {  
   
     public long getSizeLimit() {  
         return 10000000;  
     }  
 } 

O getSizeLimit informa o tamanho máximo de um arquivo para upload. tenta aumentar (esse ta ± 10 MB) e ve se é esse o problema.

[]'s

funciona assim:

se vc usa um arquivo maior q o permitido ele vai adicionar um erro de validação (isso faz precisar do hamcrest) e vai chamar a sua lógica com todos os parâmetros nulos…

a primeira linha da sua lógica deve ser:

validator.onErrorRedirectTo(this).formUpload();

ou algo do tipo

Lucas

Então a classe UploadConfig que eu criei não está fazendo o devido efeito de aumentar o limite máximo de tamanho?

Lucas, Mario e Garcia

Obrigado pela ajuda.

Depois do comentário do Lucas de que eu o problema ainda era o tamanho, voltei à mensagem do Mario e localizaei meu erro.

Minha classe UploadConfig estava marcada com @SessionScoped, mas não com @Component.

Valew

UploadConfig deveria ser @ApplicationScoped, a menos que vc precise de informações da sessão

[]'s

Lucas

Valew

Eu coloquei @ApplicationScoped na minha classe e escrevi aqui @SessionScoped.

E está funcionando legal.

Abraço