Upload GAE (Blobstore) entidade chegando null

não consegui testar aqui (a versão do meu plugin do gae tá desatualizada)
mas testa isso:

  • remova o AppEngineMultipartInterceptor do vraptor-gae.jar
  • remova os jars commons-fileupload e commons-io
  • troque os jars do pico pelos do spring

isso deveria funcionar

[quote=Lucas Cavalcanti]não consegui testar aqui (a versão do meu plugin do gae tá desatualizada)
mas testa isso:

  • remova o AppEngineMultipartInterceptor do vraptor-gae.jar
  • remova os jars commons-fileupload e commons-io
  • troque os jars do pico pelos do spring

isso deveria funcionar[/quote]

só trocando pelo pico esta funcionando tudo como deveria … o request não chega mais null se precisar …e o vraptor voltou a popular corretamente a entidade…é algo com o spring mesmo que ta fazendo o request ficar null …e assim atrapalhando o vraptor a popular automatico a entidade…

public void saveOrUpdate(Explicacao explicacao) throws IOException  {			
			Map<String, BlobKey> blobs = blobStoreService.getUploadedBlobs(request);
			BlobKey fotoKey = blobs.get("foto");
			if (fotoKey != null) {
				explicacao.setUrl(fotoKey.getKeyString());
			}
			result.include("operation", daoExplicacao.saveOrUpdate(explicacao));
			result.redirectTo(this).message();
	}

Resumindo a unica coisa que fiz foi trocar pelo pico container…

Abraços

[quote=Lucas Cavalcanti]não consegui testar aqui (a versão do meu plugin do gae tá desatualizada)
mas testa isso:

  • remova o AppEngineMultipartInterceptor do vraptor-gae.jar
  • remova os jars commons-fileupload e commons-io
  • troque os jars do pico pelos do spring

isso deveria funcionar[/quote]

Ja fiz esse teste e mesmo assim chegava null utilizando o spring…

funciona por causa de um bug do vraptor+pico :stuck_out_tongue:

esse bug que o garcia-jj corrigiu: https://github.com/caelum/vraptor/issues/335

vou tentar fazer isso funcionar de qqer forma. []'s

[quote=Lucas Cavalcanti]funciona por causa de um bug do vraptor+pico :stuck_out_tongue:

esse bug que o garcia-jj corrigiu: https://github.com/caelum/vraptor/issues/335

vou tentar fazer isso funcionar de qqer forma. []'s[/quote]

Bem estranho… pq do ponto de vista do VRaptor, isso não é um fileupload. O upload é tratado pelo Blobstore e você só recebe a BlobKey já pronta. A URL que vai no seu form não é da sua aplicação, é do Google.

Uso o GAE diariamente com VRaptor e acho melhor usar o Pico mesmo. O Spring no GAE é muito lento.
Uma outra dica seria usar o scanning estático do VRaptor, rodando ele no momento do build, ao invés de usar o scanning dinâmico default que roda quando a aplicação sobe (isso faz sua instância demorar muito no GAE).

No meu build.xml, tenho:

	<target name="cpscan" depends="compile, prepare-to-production">
		<java fork="true" classname="br.com.caelum.vraptor.scan.VRaptorStaticScanning"
			  classpathref="project.classpath">
		</java>
	</target>

O VRaptor intercepta as requisições ah*. Sendo assim o request é lido como multipart.

Verdade, tem um ano que abri essa issue: https://github.com/caelum/vraptor/issues#issue/203
Aqui no projeto tenho um hack pra ele não filtrar ah*


Mas de qualquer forma, o pau que tá dando não é no request ah* do BlobStore, é no request seguinte, quando o BlobStore redireciona pra URL da aplicação. Nesse request seguinte, acho que não é multipart (será?), porque o arquivo foi tratado no request anterior do BlobStore

Será que por padrão não interceptar as páginas ah* é correto? Pergunto isso porque será que não haverá casos onde precisariamos interceptar essas páginas? Pergunto para ti isso porque sei que tu tens muita experiência no GAE/J.

Uma sugestão que o Lucas deu foi de dar suporte ao blobstore como multipart-interceptor.

Pro GAE, eu acho correto não filtrar _ah*. Esses endereços são usados só pelo GAE (login, blobstore, painel de admin etc).
O usuário até pode configurar uma URL da aplicação como _ah/blabla mas isso é feio; acho razoável assumir que as URLs _ah* são sempre do GAE e não da aplicação.

E do Blobstore passar pelo VRaptor, acho que não tem como. Não tem uma API pra inserir no Blobstore arbitrariamente, apenas usando o mecanismo dele de upload pelo BlobstoreService. Acho que o VRaptor não deve se meter nisso. Precisamos só descobrir direito qual foi o bug que fez os parâmetros não chegarem direito no Spring

O bug é porque o pico não estava processando upload no GAE. Houve uma correção há alguns dias para isso.

Oi pessoal. Não sei se esse tópico já é assunto superado, mas estou passando pelo problema e fiquei com uma dúvida.

No caso, estou conseguindo acessar todos os campos do meu formulário original via request.getParameter(). O “problema” é que eu não gostaria de perder a praticidade que o VRaptor me dá para povoar o objeto que é parâmetro de entrada do método. Então, a pergunta é: uma vez que o código do meu método começou a ser executado, há como eu passar, por exemplo, o request para alguma classe do VRaptor, de forma que essa chamada caia num outro método com as propriedades de meu objeto de entrada já setadas?

Não sei se expliquei direito a dúvida. Qualquer coisa posso tentar detalhar melhor…

vc não pode receber o objeto que vc quer que seja populado no método do controller?

Teoricamente sim. Mas, por algum motivo que não sei explicar, se o método do controller tiver algum parâmetro, eu volto a receber a exceção lá do começo da thread. Meu código só funcionou quando comecei a usar um método sem parâmetros…

ah, isso acontece só nos uploads…

o que a gente geralmente faz (e mtos sistemas fazem) é separar o upload do resto dos dados… ou seja, vc usa um form só pro upload e o resto dos dados vc seta em outro lugar

Pois eh, eu acabei fazendo isso, mas continuei pensando a respeito e fiquei com a impressão que o processo fica “burocrático” assim. Inclusive em outro sistema que tinha feito, os casos de upload fiz em forms separados…

De qualquer maneira, separar o cadastro em dois forms me gera um problema em potencial: detectar blobs orfãos na blobstore (para o caso do formulário seguinte não ser persistido. Acho que isso é uma questão para a lista do GAE (na verdade, já postei isso lá), mas (por curiosidade) alguém aqui do forum, que desenvolve para o GAE, já se preocupou com isso?

Olá pessoal!
Tenho um assunto que anda no mesmo caminho, então não vou criar uma nova discussão.

após chamar a url de upload gerada (_ah*) o próprio GAE me redireciona pra URL que eu informei no método createUploadUrl() certo?
Estou obtendo um 404 nessa requisição para a url de callback que informei nesse método.

03:10:54,146 DEBUG [VRaptor ] VRaptor received a new request ... Request components are ... 03:10:54,146 DEBUG [PicoComponentRegistry] There's no @SessionScoped component, so skipping session container creation 03:10:54,157 DEBUG [PicoComponentAdapter] New adapter for app.infra.CriadorDeSessaoDB 03:10:54,160 DEBUG [ToInstantiateInterceptorHandler] Invoking interceptor ResourceLookupInterceptor 03:10:54,161 DEBUG [DefaultResourceTranslator] trying to access /_ah/upload/agtjb3JyZXRvcnJtanIbCxIVX19CbG9iVXBsb2FkU2Vzc2lvbl9fGFsM Jul 18, 2011 12:10:54 AM com.google.appengine.tools.development.LocalResourceFileServlet doGet WARNING: No file found for: /fotos

Ele tenta procurar por um arquivo e não acha?
Fiz um teste básico aqui apenas com servlet. A requisição para url de callback foi feita certinho.

Valeu :slight_smile:

Isso funciona bem aqui. Cola ai o trecho de código do JSP onde vc faz o upload, e o método do seu controller que deve receber a chamada da blobstore…

@Post("/fotos") public void create(Foto foto) { Map&lt;String, BlobKey&gt; blobs = blobService.getUploadedBlobs(request); BlobKey blobKey = blobs.get("arquivo"); }

&lt;form action="&lt;%= blobstoreService.createUploadUrl("/fotos") %&gt;&quot; method=&quot;post&quot; enctype=&quot;multipart/form-data&quot;&gt; <p>&lt;input type="file" name="arquivo"&gt;</p> <p>&lt;input class="buttons" type="submit" value="Salvar"/&gt;</p> &lt;/form&gt;

É isso aí.
Agora o método create() não chega nem a ser chamado.
Dá 404. Já quando eu faço uma requisição pra ele pelo form, ele é chamado normalmente.

Experimenta tirar o argumento do método create. Deixa assim:

@Post("/fotos") public void create() { Map<String, BlobKey> blobs = blobService.getUploadedBlobs(request); BlobKey blobKey = blobs.get("arquivo"); }