[Resolvido] - GAE Blobstore + VRaptor

E ai pessoal, estou tentando fazer um upload de arquivo no GAE utilizando o Blobstore, onde tenho o seguinte codigo:

	@Get
	@Path("/acomodacao/upload-fotos/{acomodacao.id}")
	public void uploadFotos(Acomodacao acomodacao){
		result.include("url", blobstore.createUploadUrl("/acomodacao/upload/"));
		result.include("acomodacao", acomodacao.getId());
	}
	
	@Post
	@Path("/acomodacao/upload/")
	public void upload(String key){
		//req é uma instancia do HttpServletRequest injetado pelo VRaptor.
		Map<String, BlobKey> blobs = blobstore.getUploadedBlobs(req);
        BlobKey blobKey = blobs.get("foto");
	}

Só que esta me dando o seguinte erro:

[quote]HTTP ERROR 500

Problem accessing /_ah/upload/aglub19hcHBfaWRyGwsSFV9fQmxvYlVwbG9hZFNlc3Npb25fXxgQDA. Reason:

INTERNAL_SERVER_ERROR

Caused by:

java.lang.UnsupportedOperationException
at java.util.Collections$UnmodifiableMap.put(Collections.java:1285)
at com.google.appengine.api.blobstore.dev.UploadBlobServlet$2.getParameterMap(UploadBlobServlet.java:267)
at javax.servlet.ServletRequestWrapper.getParameterMap(ServletRequestWrapper.java:169)
at br.com.caelum.vraptor.http.VRaptorRequest.getParameterMap(VRaptorRequest.java:80)
at br.com.caelum.vraptor.http.VRaptorRequest.getParameterNames(VRaptorRequest.java:66)
at br.com.caelum.vraptor.interceptor.ParametersInstantiatorInterceptor.intercept(ParametersInstantiatorInterceptor.java:74)
at br.com.caelum.vraptor.core.LazyInterceptorHandler.execute(LazyInterceptorHandler.java:59)
at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:53)
at br.com.caelum.vraptor.interceptor.InstantiateInterceptor.intercept(InstantiateInterceptor.java:42)
at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54)
at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:53)
at br.com.caelum.vraptor.acesso.LoginInterceptor.intercept(LoginInterceptor.java:33)
at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54)
at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:53)
at br.com.caelum.vraptor.interceptor.InterceptorListPriorToExecutionExtractor.intercept(InterceptorListPriorToExecutionExtractor.java:44)
at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54)
at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:53)
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:53)
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:53)
at br.com.caelum.vraptor.interceptor.multipart.CommonsUploadMultipartInterceptor.intercept(CommonsUploadMultipartInterceptor.java:102)
at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54)
at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:53)
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.guice.GuiceProvider.provideForRequest(GuiceProvider.java:75)
at br.com.caelum.vraptor.VRaptor.doFilter(VRaptor.java:89)
at br.com.caelum.vraptor.provider.VRaptorGAE.doFilter(VRaptorGAE.java:29)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:388)
at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:182)
at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:765)
at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:418)
at com.google.apphosting.utils.jetty.DevAppEngineWebAppContext.handle(DevAppEngineWebAppContext.java:70)
at org.mortbay.jetty.servlet.Dispatcher.forward(Dispatcher.java:327)
at org.mortbay.jetty.servlet.Dispatcher.forward(Dispatcher.java:126)
at com.google.appengine.api.blobstore.dev.UploadBlobServlet.handleUpload(UploadBlobServlet.java:380)
at com.google.appengine.api.blobstore.dev.UploadBlobServlet.access$000(UploadBlobServlet.java:72)
at com.google.appengine.api.blobstore.dev.UploadBlobServlet$1.run(UploadBlobServlet.java:101)
at java.security.AccessController.doPrivileged(Native Method)
at com.google.appengine.api.blobstore.dev.UploadBlobServlet.doPost(UploadBlobServlet.java:98)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:713)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:806)
at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:511)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1166)
at br.com.caelum.vraptor.provider.VRaptorGAE.doFilter(VRaptorGAE.java:27)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at com.google.appengine.api.blobstore.dev.ServeBlobFilter.doFilter(ServeBlobFilter.java:58)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at com.google.apphosting.utils.servlet.TransactionCleanupFilter.doFilter(TransactionCleanupFilter.java:43)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at com.google.appengine.tools.development.StaticFileFilter.doFilter(StaticFileFilter.java:122)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:388)
at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:182)
at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:765)
at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:418)
at com.google.apphosting.utils.jetty.DevAppEngineWebAppContext.handle(DevAppEngineWebAppContext.java:70)
at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
at com.google.appengine.tools.development.JettyContainerService$ApiProxyHandler.handle(JettyContainerService.java:349)
at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
at org.mortbay.jetty.Server.handle(Server.java:326)
at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:542)
at org.mortbay.jetty.HttpConnection$RequestHandler.content(HttpConnection.java:938)
at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:755)
at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:218)
at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404)
at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:409)
at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:582)[/quote]

Alguma dica

em algum canto ele tá fazendo

request.getParameterMap().put(alguma coisa)

e isso dá essa exception…

esse blobstore vem da onde?

É uma instância de BlobstoreService, injetado pelo VRaptor.

vc tem alguma lógica que dá match em

/_ah/upload/aglub19hcHBfaWRyGwsSFV9fQmxvYlVwbG9hZFNlc3Npb25fXxgQDA

?

@Post @Path("/acomodacao/upload/{key}") public void upload(String key){ //req é uma instancia do HttpServletRequest injetado pelo VRaptor. Map<String, BlobKey> blobs = blobstore.getUploadedBlobs(req); BlobKey blobKey = blobs.get("foto"); }

Esse codigo acima era para ser chamado depois do upload, onde a chave criada eu iria gravar numa entidade que criei.

Pelo que eu entendi, depois do upload feito, o metodo blobstore.createUploadUrl("/acomodacao/upload/"), redicionaria para a minha logica, vendo pelo /_ah/admin do GAE, eu vejo que o arquivo foi salvo, mais eu não consigo fazer com ele vá para a minha lógica para que eu possa gravar a chave que ele gera desse arquivo.

chega a entrar nesse método de upload?

Não, simplesmente da a exception.

O .jsp esta assim:

<form action="${url}" method="post" enctype="multipart/form-data">
            <input type="hidden" name="acomodacao.id" value="${acomodacao}" />
            <input type="file" name="foto" />
            <input type="submit" value="Fazer Upload" />
        </form>

vc precisa q o VRaptor ignore a url de upload completamente…

crie essa classe:

public class CustomVRaptor extends VRaptor {

	@Override
	public void doFilter(ServletRequest req, ServletResponse res,
			FilterChain chain) throws IOException, ServletException {

		String uri = ((HttpServletRequest)req).getRequestURI();

		if (uri.startsWith("/_ah/upload")) {
			chain.doFilter(req, res);
		} else {
			super.doFilter(req, res, chain);
		}
	}
}

e substitua o filtro do VRaptor por essa classe

ve se isso resolve

Agora me parece que deu certo, mais ainda falta uma coisa.

No redirecionamento para /acomodacao/upload/, esta dando erro 404.

Adicionei um upload.jsp na pasta de acomodacao e ainda continua dando pagina não encontrada.

tá dando 404 pq a lógica tá anotada com:

@Path("/acomodacao/upload/{key}")

então ou vc passa uma key, ou vc tira ela do @Path

Se eu tirar o parametro {key}, da a exception que postei por primeiro, agora se colocar a {key} e passar um parametro pra ela ou não da erro de 404.

qual é a url que o blobstore chama? vc consegue ver no log do vraptor?

A url que ele chama e aparece no log:

Que seria a chave do arquivo que ele cria.

Observando melhor, o erro parece que se inicia em:

Que é o filtro que eu extendi de VRptor para fazer o upload.

if (uri.startsWith("/_ah/upload/")) { chain.doFilter(req, res); } else { super.doFilter(req, res, chain); }

Esse erro da nessa linha chain.doFilter(req, res);

sim, mas isso é pq o VRaptor tá passando a requisição pra frente…

no html q tem o formulário ele faz requisição pra qual url?

<form action="/_ah/upload/aglub19hcHBfaWRyGwsSFV9fQmxvYlVwbG9hZFNlc3Npb25fXxgSDA" method="post" enctype="multipart/form-data"> <input type="hidden" name="acomodacao.id" value="4" /> <input type="file" name="foto" /> <input type="submit" value="Submit" /> </form>

O codigo fonte do formulario.

se vc trocar o

blobstore.createUploadUrl("/acomodacao/upload/")

por

blobstore.createUploadUrl("/casa/da/mae/joana")

dá 404?

Sim, ainda dá 404.

Resolvido.

Retirei o parametro do metodo upload, e funcionou.

Dai pra pegar o parametro que eu estou precisando eu usei esse codigo:

Agora esta funcionando.
Valeu Lucas mais uma vez.