[Resolvido] Upload de arquivos no VRaptor 3: configurando tamanho máximo do arquivo

Olá pessoal, tudo bem?

Sou novo na utilização do VRaptor 3 e estou tendo alguns problemas com o upload de arquivos.
Quando o arquivo está dentro do limite especificado pela classe DefaultMultipartConfig (2MB), tudo ocorre normalmente.
Minha dúvida está em dois pontos:

  • Como informar ao usuário que ele informou um arquivo maior que o limite permitido?
  • Como alterar o tamanho limite de upload para outro valor?

Na minha primeira dúvida, ao informar um arquivo com tamanho maior que 2MB, na minha aplicação ocorre a seguinte exceção:

15:28:40,359  WARN [MultipartInterceptor] There was some problem parsing this multipart request, or someone is not sending a RFC1867 compatible multipart request.
org.apache.commons.fileupload.FileUploadBase$SizeLimitExceededException: the request was rejected because its size (2580998) exceeds the configured maximum (2097152)
	at org.apache.commons.fileupload.FileUploadBase$FileItemIteratorImpl.<init>(FileUploadBase.java:914)
	at org.apache.commons.fileupload.FileUploadBase.getItemIterator(FileUploadBase.java:331)
	at org.apache.commons.fileupload.FileUploadBase.parseRequest(FileUploadBase.java:349)
	at org.apache.commons.fileupload.servlet.ServletFileUpload.parseRequest(ServletFileUpload.java:126)
	at br.com.caelum.vraptor.interceptor.multipart.MultipartInterceptor.intercept(MultipartInterceptor.java:84)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:46)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
	at br.com.caelum.vraptor.core.DefaultRequestExecution.execute(DefaultRequestExecution.java:62)
	at br.com.caelum.vraptor.VRaptor$1.insideRequest(VRaptor.java:91)
	at br.com.caelum.vraptor.ioc.spring.SpringProvider.provideForRequest(SpringProvider.java:55)
	at br.com.caelum.vraptor.VRaptor.doFilter(VRaptor.java:88)
	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:128)
	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:286)
	at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:845)
	at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
	at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
	at java.lang.Thread.run(Thread.java:619)

Esse erro é lançado dentro do bloco try na linha 4 do código abaixo (MultipartInterceptor):

...
List<FileItem> fileItems;
try {
   fileItems = fileUploadHandler.parseRequest(request);
} catch (FileUploadException e) {
   logger.warn("There was some problem parsing this multipart request, "
                  + "or someone is not sending a RFC1867 compatible multipart request.", e);
   stack.next(method, instance);
   return;
}
...
new MultipartItemsProcessor(fileItems, request, parameters).process();
...

No caso, trata-se de um SizeLimitExceededException. Quando esse erro ocorre em MultipartInterceptor, o erro é logado e a requisição continua a ser processada pelo stack de filtros.
O problema aqui é que como os campos do formulário são montados mais abaixo (linha 12), são fornecidos valores null para os controllers caso estejam esperando dados do formulario.

Essa situação pode ser reproduzida na aplicação de exemplo vraptor3-my-dvds que está no site do vraptor3 para download.
Basta informar um arquivo maior do que 2MB no upload da imagem que ocorrerá um NullPointerException (porque o DVD fornecido para o método add é null, já que os campos do formulário não foram montados devido ao erro do tamanho do arquivo).

Esse erro no tamanho do arquivo só é logado e não tenho como descobrir se ocorreu esse erro no processamento da requisição para poder avisar o usuário.

Alguém sabe se estou fazendo alguma coisa de errado ou como fazer para resolver esse problema?
Valeu pessoal!
Ass: Fernando

Basta você sobrescrever o componente DefaultMultipartConfig.

[code]@Component
@ApplicationScoped
public class CustomMultipartConfig extends DefaultMultipartConfig {

public long getSizeLimit() {
	return meu-valor-aqui;
}

}[/code]

Olá, Garcia, obrigado pela resposta!
O ajuste do tamanho deu certo. Estou enviando a classe que estou usando para configurar o tamanho no web.xml (pra contribuir caso alguém busque por algo semelhante)

CustomMultipartConfig.java

import javax.servlet.ServletContext;

import org.apache.log4j.Logger;

import br.com.caelum.vraptor.interceptor.multipart.DefaultMultipartConfig;
import br.com.caelum.vraptor.ioc.ApplicationScoped;
import br.com.caelum.vraptor.ioc.Component;

@Component  
@ApplicationScoped  
public class CustomMultipartConfig extends DefaultMultipartConfig {
	private static final Logger LOG = Logger.getLogger(CustomMultipartConfig.class);
	private static final String SIZE_LIMIT_CTX_PARAM = "br.com.caelum.vraptor.interceptor.multipart.UPLOAD_SIZE_LIMIT";
	private long sizeLimit;
	
	public CustomMultipartConfig(ServletContext ctx) {
		sizeLimit = super.getSizeLimit();
		String value = ctx.getInitParameter(SIZE_LIMIT_CTX_PARAM);
		if(value != null){
			try{
				sizeLimit = Long.parseLong(value);
			}
			catch(NumberFormatException e){
				LOG.error("Error trying do convert value \"" + value + "\" to number. Using the default size " + sizeLimit, e);
			}
		}
	}
	
    public long getSizeLimit() {
    	return sizeLimit;
    }  
} 

E para configurar, adicionar o seguinte no web.xml:

	<context-param>
		<description>Limite máximo em bytes</description>
		<param-name>br.com.caelum.vraptor.interceptor.multipart.UPLOAD_SIZE_LIMIT</param-name>
		<param-value>3145728</param-value>
	</context-param>

Como eu poderia fazer para avisar ao usuário que o arquivo que ele informou excede o limite?
Eu estou pensando em criar um novo MultipartInterceptor que trate a exceção do modo como quero (nos mesmos moldes do que foi feito acima). Existe outra forma de se fazer isso?

Valeu novamente!
Ass: Fernando

acho que vc vai ter que criar um outro MultipartInterceptor mesmo =(

vou mudar o código do vraptor pra ele adicionar um erro de validação qdo acontecer isso…

Mas o correto disso não é tratar a exception ao invés de usar o validator?

não sei se é uma exceção tratável… se vc tem um size limit e ultrapassou ele é pq não vai terminar a requisição… vai voltar pro form falando pro usuário mandar um arquivo menor

Olá, Lucas, obrigado pela resposta!

Depois de lutar um pouco consegui chegar a uma solução que em um primeiro momento me pareceu satisfatória.
Quais são os problemas:

  • Avisar ao usuario que o tamanho do arquivo que ele tentou mandar excedeu o limite
  • Quando o usuario envia um arquivo com tamanho maior que o limite o processamento continua sem que os campos do form sejam processados, passando argumentos null para o controller, mesmo quando esses campos foram preenchidos.

A ação do meu form invoca um método semelhante a esse:

public void salvar(String msg, UploadedFile anexo){
   ...
}

Se o anexo for maior que o limite, os dois campos recebidos no método são null, mesmo que “msg” tenha sido preenchido no form.
No meu caso, seria bom receber o valor do campo msg mesmo que o anexo seja maior que o limite. Nesse caso, seria bom receber um UploadedFile que pudesse me indicar de alguma maneira que ele excedeu o limite, como o código abaixo (chamei todas as minhas classes de CustomXXX por falta de criatividade ;). Os códigos completos que fiz estão em anexo) :

CustomUploadedFile.java

public class CustomUploadedFile implements UploadedFile{
	
	private boolean sizeLimitExceeded;
	private UploadedFile delegate;
	
	public CustomUploadedFile(UploadedFile delegate, boolean sizeLimitExceeded) {
		this.delegate = delegate;
		this.sizeLimitExceeded = sizeLimitExceeded;
	}

	@Override
	public String getContentType() {
		return delegate.getContentType();
	}

	@Override
	public InputStream getFile() {
		return delegate.getFile();
	}

	@Override
	public String getFileName() {
		return delegate.getFileName();
	}

	public boolean wasSizeLimitExceeded() {
		return sizeLimitExceeded;
	}
}

Essa classe possui uma indicação de que o tamanho do anexo excedeu o limite permitido.
Para que essa classe seja recebida pelo controller, criei as classes abaixo:

CustomMultipartController.java

@Component
@RequestScoped
public class CustomMultipartInterceptor extends MultipartInterceptor{

        .... removi o codigo que vinha aqui para melhorar o processamento do javascript ao acessar a thread no forum (ver codigo completo no arquivo em anexo) .... 

	@SuppressWarnings("unchecked")
	public void intercept(InterceptorStack stack, ResourceMethod method, Object instance) throws InterceptionException {
		logger.debug("Trying to parse multipart request.");

		File temporaryDirectory = config.getDirectory();

		FileItemFactory factory = createFactoryForDiskBasedFileItems(temporaryDirectory);

		List<CustomFileItem> fileItems = new ArrayList<CustomFileItem>();
		
		// Classe CustomServletFileUpload tem como caracteristica retornar uma lista de 
		// CustomFileItem. CustomFileItem tem metodo isSizeLimitExceeded usado na validacao nos controllers
		// para determinar o comportamento a ser tomado se o arquivo tem tamanho > limite...
		//
		CustomServletFileUpload upload = new CustomServletFileUpload(factory);
		
		// alterei setSizeMax (tamanho maximo da requisicao) por setFileSizeMax (tamanho maximo do arquivo).
		// Isso porque se existirem 2 arquivos a serem anexados em um form (dois inputs tipo "file"), quero 
		// que cada um deles tenha o tamanho maximo de sizeLimit. Se eu usasse setSizeMax, a soma do tamanho
		// dos dois arquivos precisaria ser < sizeLimit
		upload.setFileSizeMax(sizeLimit);
		
		try {
			fileItems = upload.parseRequest(request);
		} catch (FileUploadException e) {
			logger.warn("There was some problem parsing this multipart request, or someone is not sending a RFC1867 compatible multipart request.", e);
			stack.next(method, instance);
			return;
		}

		// Cria CustomUploadedFile (classe que tem informacao se o upload ultrapassou o limite)  
		new CustomMultipartItemsProcessor(fileItems, request, parameters).process();

		stack.next(method, instance);

		// TODO should we delete the temporary files afterwards or onExit as
		// done by now? maybe also a config in .properties

	}

        .... removi o codigo que vinha aqui para melhorar o processamento do javascript ao acessar a thread no forum (ver codigo completo no arquivo em anexo) .... 
}

CustomFileItem.java

public class CustomFileItem implements FileItem{
	
	private static final long serialVersionUID = 1L;
	private FileItem delegate;
	private boolean sizeLimitExceeded;
	
	public CustomFileItem(FileItem delegate) {
		this.delegate = delegate;
	}
        .... removi o codigo que vinha aqui para melhorar o processamento do javascript ao acessar a thread no forum (ver codigo completo no arquivo em anexo) .... 

	public void setSizeLimitExceeded(boolean b) {
		this.sizeLimitExceeded = b;
	}
	
	public boolean wasSizeLimitExceeded(){
		return sizeLimitExceeded;
	}
}

CustomServletFileUpload.java (importante colocar essa classe no pacote org.apache.commons.fileupload para ter acesso à classe MultipartStream.ProgressNotifier)
OBS: CustomFileItemIteratorImpl é uma cópia completa da classe FileItemIteratorImpl do apache commons upload. Copiei ela porque queria comentar o trecho de código “itemStream.close(true);” no método “raiseError” de “LimitedInputStream” na construtora de FileItemStreamImpl… Quando ocorre um FileSizeLimitExceededException, o inputStream é fechado, não permitindo que os demais campos do formulario sejam processados…

public class CustomServletFileUpload extends ServletFileUpload{

    public CustomServletFileUpload() {
        super();
    }

    public CustomServletFileUpload(FileItemFactory fileItemFactory) {
        super(fileItemFactory);
    }
	
	@Override
	public List /*CustomFileItem*/ parseRequest(HttpServletRequest request) throws FileUploadException {
		return parseRequest(new ServletRequestContext(request));
	}
	
	@Override
	public List /*CustomFileItem*/ parseRequest(RequestContext ctx) throws FileUploadException {
        try {
            FileItemIterator iter = getItemIterator(ctx);
            List items = new ArrayList();
            FileItemFactory fac = getFileItemFactory();
            if (fac == null) {
                throw new NullPointerException("No FileItemFactory has been set.");
            }
            while (iter.hasNext()) {
                FileItemStream item = iter.next();
                CustomFileItem fileItem = new CustomFileItem(fac.createItem(item.getFieldName(),
                        item.getContentType(), item.isFormField(),
                        item.getName()));
                try {
                    Streams.copy(item.openStream(), fileItem.getOutputStream(), true);
                } catch (FileUploadIOException e) {
                	// caso a excecao seja de tamanho limite excedido, configura a flag
                	// de tamanho excedido no item e continua o processamento dos demais
                	// parametros do request
                	if(e.getCause() instanceof FileSizeLimitExceededException){
                		FileSizeLimitExceededException exception = (FileSizeLimitExceededException) e.getCause();
                		// se quiser obter o tamanho maximo lido: exception.getActualSize()  
                		fileItem.setSizeLimitExceeded(true); 
                	}
                	else{
                		throw (FileUploadException) e.getCause();
                	}
                } catch (IOException e) {
                    throw new IOFileUploadException(
                            "Processing of " + MULTIPART_FORM_DATA
                            + " request failed. " + e.getMessage(), e);
                }
                if (fileItem instanceof FileItemHeadersSupport) {
                    final FileItemHeaders fih = item.getHeaders();
                    ((FileItemHeadersSupport) fileItem).setHeaders(fih);
                }
                items.add(fileItem);
            }
            return items;
        } catch (FileUploadIOException e) {
            throw (FileUploadException) e.getCause();
        } catch (IOException e) {
            throw new FileUploadException(e.getMessage(), e);
        }
	}
	
        .... removi o codigo que vinha aqui para melhorar o processamento do javascript ao acessar a thread no forum (ver codigo completo no arquivo em anexo) .... 

CustomMultipartItemsProcessor.java

/**
 * Copiado de br.com.caelum.vraptor.interceptor.multipart.MultipartItemsProcessor,
 * mas ao inves de montar UploadedFile, monta CustomUploadedFile (que contem indicacao de que o
 * upload foi excedido)
 * */
public class CustomMultipartItemsProcessor {
    private static final Logger logger = LoggerFactory.getLogger(CustomMultipartItemsProcessor.class);
    private final List<CustomFileItem> items;
    private final HttpServletRequest request;
    private final MutableRequest parameters;

    public CustomMultipartItemsProcessor(List<CustomFileItem> items, HttpServletRequest request, MutableRequest parameters) {
        this.items = items;
        this.request = request;
        this.parameters = parameters;
    }

    public void process() {
    	Multimap<String, String> params = LinkedListMultimap.create();
        for (CustomFileItem item : items) {
            if (item.isFormField()) {
                params.put(item.getFieldName(), item.getString());
                continue;
            }
            if (notEmpty(item)) {
                try {
                    CustomUploadedFile fileInformation = new CustomUploadedFile(new DefaultUploadedFile(item.getInputStream(), item.getName(), item.getContentType()), item.wasSizeLimitExceeded());
                    parameters.setParameter(item.getFieldName(), item.getName());
                    request.setAttribute(item.getName(), fileInformation);

                    logger.debug("Uploaded file: " + item.getFieldName() + " with " + fileInformation);
                } catch (Exception e) {
                    throw new InvalidParameterException("Cant parse uploaded file " + item.getName(), e);
                }
            } else {
                logger.debug("A file field was empty: " + item.getFieldName());
            }
        }
        for (String paramName : params.keySet()) {
			Collection<String> paramValues = params.get(paramName);
			parameters.setParameter(paramName, paramValues.toArray(new String[paramValues.size()]));
		}
    }
    
    private static boolean notEmpty(FileItem item) {
        return !item.getName().trim().equals("");
    }
}

Bom, depois disso tudo, altero meu controller anterior para ficar como abaixo:

public void salvar(String msg, CustomUploadedFile anexo){
   if(anexo.wasSizeLimitExceeded()){
       result.include("msg", msg);
       result.include("erros", new String[]{"O tamanho do arquivo a ser anexado deve ser menor que XXX MB"});
       return;
   }
   ...
}

Desse modo o form é exibido novamente exibindo a mensagem de erro e com o campo msg devidamente populado com o valor submetido.
Pelo que pude testar hoje funcionou como eu queria, apesar de parecer xunxado :slight_smile:
Viajei na maionese?

tem um jeito mais rápido:

  try  {  
            fileItems = upload.parseRequest(request);  
  } catch (SizeLimitExceededException e) {
            validator.add(new ValidationMessage("upload", "file.limit.exceeded")); // o Validator do VRaptor
             stack.next(method, instance);  
             return;  

  } catch (FileUploadException e) {  
             logger.warn("There was some problem parsing this multipart request, or someone is not sending a RFC1867 compatible multipart request.", e);  
             stack.next(method, instance);  
             return;  
  }  

e na sua lógica

public void upload(String msg, UploadedFile file) {
     validator.onErrorUse(....)....;
     //vai vir tudo null mas vai ter um erro de validação, então vai redirecionar
     ...
}

e não precisa de nenhuma das outras classes =)

Olá Lucas!

Eu tentei fazer isso quando você informou que iria adicionar um erro de validação no vraptor.
O problema é que quando adiciono a mensagem de validação e trato o erro usando o validator, o conteúdo do campo msg some quando a página volta para o formulário para informar ao usuário que o arquivo excede o limite. Assim ele perde o que o usuário já digitou na mensagem…

Valeu!
Ass: Fernando

Nesse caso a solução é boa =)

Só toma cuidado que essas decisões de parar o processamento se o limite for excedido podem ter uma razão forte (não tenho certeza disso, precisa testar): se o cara manda um arquivo de 300 MB, e o limite é 2MB por exemplo, vc só vai conseguir receber os outros parâmetros depois de mandar os 300MB pro servidor, que é o que vc tava tentando evitar. Mas pode ser que ele mande os parâmetros “normais” antes do upload, daí isso não será problema…

o que se faz normalmente é separar o formulário de upload do resto dos dados… ou fazendo um cadastro em vários passos (como o orkut fazia há um tempo atras), ou submetendo o upload via ajax (como o gmail faz). Pra isso vc pode usar bibliotecas javascript como: http://valums.com/ajax-upload/

de qqer forma vc pode trocar:

 if(anexo.wasSizeLimitExceeded()){  
        result.include("msg", msg);  
        result.include("erros", new String[]{"O tamanho do arquivo a ser anexado deve ser menor que XXX MB"});  
        return;  
    }  

por

 if(anexo.wasSizeLimitExceeded()){  
        validator.add(new ValidationMessage("upload", "O tamanho do arquivo a ser anexado deve ser menor que XXX MB"));
  }
  validator.onErrorUse(logic())....

Blz. Valeu pelas observações!
Vou usar o validator.
Vou dar uma pesquisada melhor nesses aspectos que você mencionou. Se eu chegar em algum lugar com o upload eu posto aqui.

Valeu!
Ass: Fernando

Obrigado pessoal, passei tb por este problema e consegui resolver com a discussão acima.

fllws

Bom dia pessoal,

Estou com problemas ao controlar o tamanho do arquivo.

Com a classe CustomMultipartConfig (extends DefaultMultipartConfig), consigo limitar o tamanho, porém não consegui ainda controlar a exception.

Creio que a exception que está dando aqui, não é exatamente a que deveria ocorrer:

11:13:49,604 INFO  [STDOUT] 11:13:49,604 INFO  [CommonsUploadMultipartInterceptor] Request contains multipart data. Try to parse with commons-upload.
11:13:49,612 ERROR [[default]] Servlet.service() for servlet default threw exception
java.lang.ClassNotFoundException: org.hamcrest.Description from BaseClassLoader@444c18{vfsfile:/C:/java/EclipseJBoss/jboss-eap/jboss-as/server/default/deploy/Teste.war/}
	at org.jboss.classloader.spi.base.BaseClassLoader.loadClass(BaseClassLoader.java:477)
	at java.lang.ClassLoader.loadClass(Unknown Source)
	at br.com.caelum.vraptor.interceptor.multipart.CommonsUploadMultipartInterceptor.reportSizeLimitExceeded(CommonsUploadMultipartInterceptor.java:145)
	at br.com.caelum.vraptor.interceptor.multipart.CommonsUploadMultipartInterceptor.intercept(CommonsUploadMultipartInterceptor.java:124)
	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.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.EnhancedRequestExecution.execute(EnhancedRequestExecution.java:23)
	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.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:96)
	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:235)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
	at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:183)
	at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:95)
	at org.jboss.web.tomcat.security.SecurityContextEstablishmentValve.process(SecurityContextEstablishmentValve.java:126)
	at org.jboss.web.tomcat.security.SecurityContextEstablishmentValve.invoke(SecurityContextEstablishmentValve.java:70)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
	at org.jboss.web.tomcat.service.jca.CachedConnectionValve.invoke(CachedConnectionValve.java:158)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:330)
	at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:829)
	at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:598)
	at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:451)
	at java.lang.Thread.run(Unknown Source)

É essa mesmo que deveria dar? Em caso positivo, alguém poderia me ajudar a controlar ela, sem estourar na tela do usuário?

Tentei com try catch no arquivo que fiz o upload, porém não consegui, acho que não entendi bem o funcionamento.

Muito obrigado desde já,
Rodrigo

o erro é um classNotFound, ou seja, falta de um jar no classpath. no caso o jar do hamcrest

Eu adicionei o .jar do hamcrest, porém agora está dando outro erro:

java.util.MissingResourceException: Can't find bundle for base name messages, locale en_US
	java.util.ResourceBundle.throwMissingResourceException(Unknown Source)
	java.util.ResourceBundle.getBundleImpl(Unknown Source)
	java.util.ResourceBundle.getBundle(Unknown Source)
	br.com.caelum.vraptor.validator.Validations.<init>(Validations.java:57)
	br.com.caelum.vraptor.interceptor.multipart.CommonsUploadMultipartInterceptor$1.<init>(CommonsUploadMultipartInterceptor.java:145)
	br.com.caelum.vraptor.interceptor.multipart.CommonsUploadMultipartInterceptor.reportSizeLimitExceeded(CommonsUploadMultipartInterceptor.java:145)
	br.com.caelum.vraptor.interceptor.multipart.CommonsUploadMultipartInterceptor.intercept(CommonsUploadMultipartInterceptor.java:124)
	br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54)
	br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54)
	br.com.caelum.vraptor.interceptor.FlashInterceptor.intercept(FlashInterceptor.java:83)
	br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54)
	br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54)
	br.com.caelum.vraptor.interceptor.ExceptionHandlerInterceptor.intercept(ExceptionHandlerInterceptor.java:71)
	br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54)
	br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54)
	br.com.caelum.vraptor.interceptor.ResourceLookupInterceptor.intercept(ResourceLookupInterceptor.java:69)
	br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54)
	br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54)
	br.com.caelum.vraptor.core.EnhancedRequestExecution.execute(EnhancedRequestExecution.java:23)
	br.com.caelum.vraptor.VRaptor$1.insideRequest(VRaptor.java:92)
	br.com.caelum.vraptor.ioc.spring.SpringProvider.provideForRequest(SpringProvider.java:58)
	br.com.caelum.vraptor.VRaptor.doFilter(VRaptor.java:89)
	org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:96)

Inicialmente ele reclamava de não achar para o pt_BR, ai alterei no servidor para en_US, porém o erro persiste.

Pesquisei a respeito, mas me pareceu ser um problema meio genérico.

Não sei o que fazer, e aparentemente esse problema está diretamente relacionado a lib do hamcrest.

Muito obrigado!

renomeie um dos arquivos pra apenas messages.properties, daí deve funcionar

Boa tarde Lucas!

Um pouco antes de ver a sua mensagem, o Wellington (wbotelhos) estava aqui na empresa e me ajudou.

Criamos o messages.properties e também configuramos ele no web.xml, agora a exception esperada está aparecendo. Vou estudar agora um pouco sobre o Validator do VRaptor para poder tratar isso certinho.

Muito obrigado Lucas!

Boa tarde Lucas,

Cara eu tentei tratar o problema do arquivo ser muito grande da forma mais simples que encontrei, que foi:

validator.onErrorUsePageOf(this).tamanhoMaximo();

Ele até que funciona e manda para o método certo, porém mesmo assim ele lança a exception, isso é normal? Eu preciso fazer todo o procedimento que a pessoa que abriu esse tópico originalmente precisou fazer para realmente resolveu o problema?

Muito obrigado!

a exception sempre vai acontecer… o VRaptor só loga ela. Não deveria afetar muito a sua aplicação.

É que por exemplo, fiz:

		validator.onErrorUsePageOf(this).problema();

E depois:


	public void problema(){
		System.out.println("Problemas...");
	}

E ele não printa o “Problemas…”, não deveria printar normalmente?

Muito obrigado!