Problema com enctype="multipart/form-data" vraptor 3.2 [RESOLVIDO]

Ai galera.
Mesmo problema aqui, tô usando Tomcat 7.02 e agora o VRaptor 3.2, o meu upload estava funcionando desde a versão 3.1 do VRaptor, li o tópico e me certifiquei que o commons-fileupload e commons-io estavam na /lib, atualizei o jar do Vraptor para 3.2.1:
http://oss.sonatype.org/content/repositories/snapshots/br/com/caelum/vraptor/3.2.1-SNAPSHOT/vraptor-3.2.1-20101021.130049-4.jar

Mesmo assim, o nome da foto (foto.nome) está chegando null no Controller:

<form action="<c:url value="/foto/${imovel.codImovel}/"/>" method="post" enctype="multipart/form-data">
    <p>Upload de Imagem<br />
    Nome: <input type="text" name="foto.nome" /><br/>
    <input type="file" name="imagem"/>
    <br>Descri&ccedil;&atilde;o:<br>    
    <textarea name="foto.descricao" rows="3" cols="40"></textarea><br>            	
  	<button type="submit">Enviar</button>  	
</form>
@Post
@Path("/foto/{imovel.codImovel}/")
public void upload(final UploadedFile imagem, final Imovel imovel, final Foto foto) {
		final Integer qtdeMaximaUpload = Integer.parseInt(this.parameterLoader.getParameter("qtde.maxima.upload"));
		validator.onErrorRedirectTo(this).adiciona(imovel.getCodImovel());
		validator.checking(new Validations() { // esta é a linha 54			
			{
				if (that(imagem, is(notNullValue()), "imagem", "imagem.nula")) {
				    that(imagem.getContentType(), startsWith("image"), "imagem", "nao.eh.imagem");
				}
					that(!foto.getNome().isEmpty(), "img.nome", "imgNome.obrigatorio"); // esta é a linha 59
					that(!(fotoDAO.getTotalFotos(imovel) >= qtdeMaximaUpload), "img.qtd", "qtd.exceed");
			}				
		});
		
		validator.onErrorRedirectTo(this).adiciona(imovel.getCodImovel());
		imagens.salva(imagem,imovel,foto);				
		// Retornando mensagem de sucesso na inclusão
		result.include("mensagem", "Imagem adicionada com sucesso");
		result.use(Results.logic()).redirectTo(FotoController.class).adiciona(imovel.getCodImovel());

	 }
Caused by: java.lang.NullPointerException
	at br.com.imobiliaria.controller.FotoController$1.<init>(FotoController.java:59)
	at br.com.imobiliaria.controller.FotoController.upload(FotoController.java:54)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:616)
	at br.com.caelum.vraptor.interceptor.ExecuteMethodInterceptor.intercept(ExecuteMethodInterceptor.java:57)
	... 85 more

tanto foto qto foto.getNome podem estar vindo nulos, cuidado com isso…

de qqer forma:
-o nome está preenchido?
-o upload é pequeno? (menos de 2Mb se vc não mudou configurações)

Pois é Lucas, o nome está preenchido no form e a imagem possui menos do limite configurado, coloquei o breakpoint lá na linha do método upload() e “foto” está vindo null, mesmo estando null, o validator deveria acusar a falta do nome e mandar a mensagem para a jsp avisando que o nome está vazio e não dar nullpointer como está acontecendo. Como disse antes, o upload estava funcionando até a versão 3.1.3.
Abraço!

o nullpointer acontece pq vc chama:

!foto.getNome().isEmpty();

vc deveria fazer:

foto != null && foto.getNome() != null && !foto.getNome().isEmpty()

não tem como o VRaptor te ajudar nisso…

vou aceitar os últimos pull requests do garcia que corrigem essa parte e já te gero um snapshot

O Tomcat 7 ainda está em beta. Será que há algum erro quanto a isso?

Outro dia reportei ao pessoal da Apache sobre um bug no servlet upload, embora o erro seja outro, pois o Vraptor não usa o servlet upload caso você tenha o commons-fileupload no classpath.

O pull que está pendente apenas exibe um warn quando não é encontrado nenhuma lib no classpath.

Guevara, você tem tanto o commons-io quando o commons-fileupload no seu classpath? Além disso qual versão você está usando do Vraptor? 3.2 ou um snapshot?

Eu estava usando o jar do VRaptor 3.2, mas aí com este problema do nullpointer fui investigar e acabei achando este tópico, o upload estava funcionando normalmente até eu migrar para o 3.2. Vou tentar da forma que o Lucas sugeriu, mas tá muito estranho essa validação, se o Lucas gerar uma forma de validar desse jeito que postei seria melhor, pelo atributo, foto.getNome().
Abraço!

vc pode fazer:

foto != null && !StringUtils.isBlank(foto.getNome())

ou ainda:

if (that(foto != null, "abc", "def")) {
   that(!StringUtils.isBlank(foto.getNome()), "", "");
}

talvez exista o isNotBlank()

[]'s

“Houston, we have a problem”: =)

@SuppressWarnings("null")
	@Post
	@Path("/foto/{imovel.codImovel}/")
	public void upload(final UploadedFile imagem, final Imovel imovel, final Foto foto) {
		final Integer qtdeMaximaUpload = Integer.parseInt(this.parameterLoader.getParameter("qtde.maxima.upload"));
		validator.onErrorRedirectTo(this).adiciona(imovel.getCodImovel());
		validator.checking(new Validations() {			
			{
				if (that(imagem, is(notNullValue()), "imagem", "imagem.nula")) {
				    that(imagem.getContentType(), startsWith("image"), "imagem", "nao.eh.imagem");
				}
					that(!(foto != null) && foto.getNome() != null && !foto.getNome().isEmpty()
, "img.nome", "imgNome.obrigatorio");
					that(!(fotoDAO.getTotalFotos(imovel) >= qtdeMaximaUpload), "img.qtd", "qtd.exceed");
			}				
		});
root cause

java.lang.NullPointerException
	br.com.imobiliaria.controller.FotoController$1.<init>(FotoController.java:60)
	br.com.imobiliaria.controller.FotoController.upload(FotoController.java:55)
	sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
	sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	java.lang.reflect.Method.invoke(Method.java:616)

vi agora seu ultimo post, vou tentar aqui

Lucas, desse jeito olha o que acontece:

15:51:18,866 DEBUG [VRaptor             ] VRaptor received a new request
15:51:18,871 DEBUG [DefaultRequestExecution] executing stack  DefaultRequestExecution
15:51:18,893 DEBUG [ToInstantiateInterceptorHandler] Invoking interceptor Servlet3MultipartInterceptor
15:51:18,893 DEBUG [Servlet3MultipartInterceptor] Request contains multipart data. Try to parse with Servlet3 Part
15:51:18,913 DEBUG [ToInstantiateInterceptorHandler] Invoking interceptor ResourceLookupInterceptor
15:51:18,913 DEBUG [DefaultResourceTranslator] trying to access /foto/100/
15:51:18,914 DEBUG [VRaptorRequest      ] Setting imovel.codImovel with [100]
15:51:18,914 DEBUG [DefaultResourceTranslator] found resource [DefaultResourceMethod: FotoController.uploadFotoController.upload(UploadedFile, Imovel, Foto)]
15:51:18,916 DEBUG [ToInstantiateInterceptorHandler] Invoking interceptor FlashInterceptor
15:51:18,918 DEBUG [ToInstantiateInterceptorHandler] Invoking interceptor InterceptorListPriorToExecutionExtractor
15:51:18,919 DEBUG [ToInstantiateInterceptorHandler] Invoking interceptor Servlet3MultipartInterceptor
15:51:18,919 DEBUG [Servlet3MultipartInterceptor] Request contains multipart data. Try to parse with Servlet3 Part
15:51:18,922 DEBUG [ToInstantiateInterceptorHandler] Invoking interceptor JPATransactionInterceptor
15:51:18,924 DEBUG [ToInstantiateInterceptorHandler] Invoking interceptor NoCacheInterceptor
15:51:18,926 DEBUG [ToInstantiateInterceptorHandler] Invoking interceptor InstantiateInterceptor
15:51:18,955 DEBUG [LazyInterceptorHandler] Invoking interceptor ParametersInstantiatorInterceptor
15:51:18,955 DEBUG [AsmBasedTypeCreator ] Trying to make class for FotoController$upload$385806064$2
15:51:18,955 DEBUG [ParanamerNameProvider] Found parameter names with paranamer for FotoController.upload(UploadedFile, Imovel, Foto) as [imagem, imovel, foto]
15:51:18,955 DEBUG [AsmBasedTypeCreator ] Parameter names found for creating type are: [Imagem, Imovel, Foto]
15:51:18,955 DEBUG [AsmBasedTypeCreator ] Method for field 'Imagem' being defined for type Lbr/com/caelum/vraptor/interceptor/multipart/UploadedFile;
15:51:18,956 DEBUG [AsmBasedTypeCreator ] Method for field 'Imovel' being defined for type Lbr/com/imobiliaria/bean/Imovel;
15:51:18,956 DEBUG [AsmBasedTypeCreator ] Method for field 'Foto' being defined for type Lbr/com/imobiliaria/bean/Foto;
15:51:18,957 DEBUG [AsmBasedTypeCreator ] Methods: [public br.com.imobiliaria.bean.Foto FotoController$upload$385806064$2.getFoto(), public void FotoController$upload$385806064$2.setImovel(br.com.imobiliaria.bean.Imovel), public br.com.imobiliaria.bean.Imovel FotoController$upload$385806064$2.getImovel(), public void FotoController$upload$385806064$2.setImagem(br.com.caelum.vraptor.interceptor.multipart.UploadedFile), public br.com.caelum.vraptor.interceptor.multipart.UploadedFile FotoController$upload$385806064$2.getImagem(), public void FotoController$upload$385806064$2.setFoto(br.com.imobiliaria.bean.Foto)]
15:51:18,957 DEBUG [AsmBasedTypeCreator ] Fields: [private br.com.caelum.vraptor.interceptor.multipart.UploadedFile FotoController$upload$385806064$2.Imagem_, private br.com.imobiliaria.bean.Imovel FotoController$upload$385806064$2.Imovel_, private br.com.imobiliaria.bean.Foto FotoController$upload$385806064$2.Foto_]
15:51:18,957 DEBUG [CacheBasedTypeCreator] cached generic type for method [DefaultResourceMethod: FotoController.uploadFotoController.upload(UploadedFile, Imovel, Foto)]
15:51:18,957 DEBUG [OgnlParametersProvider] Applying imovel.codImovel with [100]
15:51:18,965 DEBUG [ParanamerNameProvider] Found parameter names with paranamer for FotoController.upload(UploadedFile, Imovel, Foto) as [imagem, imovel, foto]
15:51:18,965 DEBUG [ParametersInstantiatorInterceptor] Parameter values for [DefaultResourceMethod: FotoController.uploadFotoController.upload(UploadedFile, Imovel, Foto)] are [null, br.com.imobiliaria.bean.Imovel@63725d, null]

15:51:18,893 DEBUG [Servlet3MultipartInterceptor] Request contains multipart data. Try to parse with Servlet3 Part

tá usando o Servlet3 =(

deveria ser o CommonsUploadMultipartInterceptor…

tem certeza que tá com o snapshot do 3.2.1? Vc chegou a apagar o jar anterior? deu clean no servidor e no eclipse?

[quote=Lucas Cavalcanti]15:51:18,893 DEBUG [Servlet3MultipartInterceptor] Request contains multipart data. Try to parse with Servlet3 Part

tá usando o Servlet3 =[/quote]

O grande problema de usar Servlet3 no Tomcat é que o suporte ainda é beta. No Glassfish, que até então é o único certificado funciona corretamente.

O desgramado estava publicado ainda, dei um clean aqui e funcionou, valeu pessoal! o/

Hoje tive um problema:

-Upload com PUT

&lt;form action="&lt;c:url value="/configuracoes/empresa/" /&gt;&quot; class=&quot;formulario&quot; method=&quot;POST&quot; enctype=&quot;multipart/form-data&quot;&gt;
	&lt;input type="hidden" name="empresa.id" value="${empresa.id}" /&gt;
	&lt;input type="hidden" name="empresa.endereco.id" value="${empresa.endereco.id}" /&gt;
	&lt;c:if test="${empresa.id &gt; 0}"&gt;
		&lt;input type="text" name="_method" value="PUT" /&gt;
	&lt;/c:if&gt;
	@Put
	@Path("/configuracoes/empresa/")
	public void Editar(Empresa empresa) {
		System.out.println("metodo editar");
	@Post
	@Path("/configuracoes/empresa/")
	public void Registrar(Empresa empresa) {
		System.out.println("metodo adicionar");

[quote]15:53:35,651 [http-8080-1] INFO CommonsUploadMultipartInterceptor - Request contains multipart data. Try to parse with commons-upload.
---------------------------------------------------------- POST
metodo adicionar[/quote]

Quanto tento sem o multipart/form-data ele entra no method PUT.
Alguma coisa que eu possa fazer quanto a isso?

não funciona usando esse PUT fake, pq o _method está dentro da requisição multipart, o server precisa parsear o multipart antes de ler o _method.

tenta colocar ?_method=PUT na url, mas mesmo assim acho que não vai rolar