VRaptor3 + GAE, parte II

Um probleminha estranho
Usando vraptor 3 - beta 4, no gae

eu tenho dois controllers, mas está instável, as vezes acha um, as vezes o outro e as vezes os dois [não aconteceu nenhuma vez de não achar nenhum, executei várias vezes e não achei nenhum padrão, e não parece ser nada cíclico
Segue o log

 (...)
 [DEBUG] 17:58:44,537 DEBUG [br.com.caelum.vraptor.core.DefaultConverters] - bundled converter to be registered: class br.com.caelum.vraptor.interceptor.multipart.UploadedFileConverter
 [INFO] 17:58:44,553 INFO  [br.com.caelum.vraptor.ioc.pico.StereotypedComponentRegistrar] - Registering all classes with stereotyped annotations (annotations annotated with @Stereotype)
 [DEBUG] 17:58:44,553 DEBUG [br.com.caelum.vraptor.ioc.pico.StereotypedComponentRegistrar] - found component: class br.med.scp.controller.CidController, annotated with: interface br.com.caelum.vraptor.Resource
 [DEBUG] 17:58:44,553 DEBUG [br.com.caelum.vraptor.ioc.pico.ResourceRegistrar] - Found resource: class br.med.scp.controller.CidController
 [DEBUG] 17:58:44,568 DEBUG [br.com.caelum.vraptor.http.route.DefaultParametersControl] - For /cids/add retrieved /cids/add with {}
 [INFO] 17:58:44,584 INFO  [br.com.caelum.vraptor.http.route.RouteBuilder] - /cids/add --> public void br.med.scp.controller.CidController.add()
 [DEBUG] 17:58:44,584 DEBUG [br.com.caelum.vraptor.http.route.DefaultParametersControl] - For /cids retrieved /cids with {}
 [INFO] 17:58:44,584 INFO  [br.com.caelum.vraptor.http.route.RouteBuilder] - /cids --> public java.util.List br.med.scp.controller.CidController.index()
 [DEBUG] 17:58:44,584 DEBUG [br.com.caelum.vraptor.ioc.pico.PicoComponentRegistry] - Registering br.med.scp.controller.CidController with br.med.scp.controller.CidController
 [INFO] 17:58:44,584 INFO  [br.com.caelum.vraptor.ioc.pico.PicoComponentRegistry] - Class being registered as @RequestScoped, since there is no Scope annotation class br.med.scp.controller.CidController
 [DEBUG] 17:58:44,584 DEBUG [br.com.caelum.vraptor.ioc.pico.PicoComponentRegistry] - Registering br.med.scp.controller.CidController as a request component
 [DEBUG] 17:58:44,599 DEBUG [br.com.caelum.vraptor.ioc.pico.ReflectionsScanner] - Found the following sterotyped annotations: []
 [DEBUG] 17:58:44,599 DEBUG [br.com.caelum.vraptor.ioc.pico.PicoComponentRegistry] - Registering br.med.scp.infra.vraptor.util.EntityTransactionCreator with br.med.scp.infra.vraptor.util.EntityTransactionCreator
 [DEBUG] 17:58:44,599 DEBUG [br.com.caelum.vraptor.ioc.pico.PicoComponentRegistry] - Overriding interface br.med.scp.infra.vraptor.util.EntityTransactionCreator with br.med.scp.infra.vraptor.util.EntityTransactionCreator
 [DEBUG] 17:58:44,599 DEBUG [br.com.caelum.vraptor.ioc.pico.PicoComponentRegistry] - Registering br.med.scp.infra.vraptor.util.EntityTransactionCreator as a request component
 [DEBUG] 17:58:44,599 DEBUG [br.com.caelum.vraptor.ioc.pico.DefaultComponentFactoryRegistry] - Registering a ComponentFactory for javax.persistence.EntityTransaction in request scope
 [DEBUG] 17:58:47,834 DEBUG [br.com.caelum.vraptor.ioc.pico.PicoComponentRegistry] - Registering br.com.caelum.vraptor.http.TypeCreator with br.com.caelum.vraptor.reflection.CacheBasedTypeCreator
 [DEBUG] 17:58:47,834 DEBUG [br.com.caelum.vraptor.ioc.pico.PicoComponentRegistry] - Overriding interface br.com.caelum.vraptor.http.TypeCreator with br.com.caelum.vraptor.reflection.CacheBasedTypeCreator
 [DEBUG] 17:58:47,849 DEBUG [br.com.caelum.vraptor.ioc.pico.PicoComponentRegistry] - Registering br.com.caelum.vraptor.reflection.CacheBasedTypeCreator as an application component
 [WARN] 17:58:47,849 WARN  [br.com.caelum.vraptor.ioc.pico.PicoComponentRegistry] - VRaptor was already initialized, the contexts were created but you are registering a component.This is nasty. The original component might already be in use.Avoid doing it: br.com.caelum.vraptor.http.TypeCreator
 [INFO] 17:58:47,896 INFO  [br.com.caelum.vraptor.VRaptor] - VRaptor 3 successfuly initialized
 The server is running at http://localhost:8080/

[]s

vc tá com a configuração:

<context-param>
		<param-name>br.com.caelum.vraptor.packages</param-name>
		<param-value>br.med.scp</param-value>
</context-param>

no seu web.xml?

os controllers estão todos no classpath?
estão no WEB-INF/classes ou dentro de jars?

você atualizou os jars do reflections e do google-collect?

[]'s

Vamos por partes

  1. sim
  &lt;context-param&gt;
	  &lt;param-name&gt;br.com.caelum.vraptor.packages&lt;/param-name&gt;
	  &lt;param-value&gt;br.med.scp&lt;/param-value&gt;
  &lt;/context-param&gt;

sim estão
br.med.scp.controller.CidController;
br.med.scp.controller.IndexController;

no classes, sem packages

WEB-INF/lib/reflections-0.9.4.jar
WEB-INF/lib/google-collect-1.0-rc2.jar

[]s

edufa, voce pode tentar com o spring pra gente ver?

e porque a preferencia pelo pico nesse caso?

Olá, usei o Spring e carregou os dois controllers.

Porém eu tinha feito um Provider usando o pico, me inspirei [copiei mesmo, rs] no calopsita

public class ScimpacProvider extends PicoProvider {

	@Override
	protected void registerBundledComponents(ComponentRegistry registry) {
		super.registerBundledComponents(registry);

		registry.register(EntityManagerCreator.class, EntityManagerCreator.class);
		registry.register(EntityManagerFactoryCreator.class, EntityManagerFactoryCreator.class);
		registry.register(Repositories.class, RepositoriesImpl.class);
	}

}

Qual a melhor maneira de fazer isso com o spring?

Sobre o motivo para escolher o pico.
Entre um jar de 3M e um de 300k, fiquei com o menor, mesmo pq não precisaria usar nada especifico do spring, assim o pico me pareceu uma escolha natural, hehehe

basta anotar as classes:

EntityManagerCreator, EntityManagerFactoryCreator.class e RepositoriesImpl

com @Component

não precisa do CustomProvider, tanto pro spring quanto pro pico…

[]'s

@lucascs

Localmente funcionou, mas qdo envio para o appengine dá erro

failed vraptor
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.context.annotation.internalPersistenceAnnotationProcessor': Initialization of bean failed; nested exception is java.lang.NoClassDefFoundError: javax/naming/NamingException
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:480)

Acontece pq javax/naming/NamingException, não está na white list do google.
Provavelmente o spring-2.5.5.jar está usando, vou tentar carregar individualmente os jars do spring ao invés de usar um único com tudo, acredito que resolva se achar a combinação certa :wink:

[]s

Investigando um pouco mais, vi algumas pessoas reclamando disso e do pacote orm do spring, como não uso o mesmo, defenestrei ele e funcionou, mas eis q aparece outro erro…

/cids
br.com.caelum.vraptor.InterceptionException: java.lang.NullPointerException
	at br.com.caelum.vraptor.interceptor.ExecuteMethodInterceptor.intercept(ExecuteMethodInterceptor.java:75)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:57)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:71)
	at br.com.caelum.vraptor.interceptor.ParametersInstantiatorInterceptor.intercept(ParametersInstantiatorInterceptor.java:95)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:57)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:71)
	at br.com.caelum.vraptor.interceptor.InstantiateInterceptor.intercept(InstantiateInterceptor.java:54)
	at br.com.caelum.vraptor.core.InstantiatedInterceptorHandler.execute(InstantiatedInterceptorHandler.java:51)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:71)
	at br.com.caelum.vraptor.interceptor.multipart.MultipartInterceptor.intercept(MultipartInterceptor.java:58)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:57)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:71)
	at br.com.caelum.vraptor.interceptor.InterceptorListPriorToExecutionExtractor.intercept(InterceptorListPriorToExecutionExtractor.java:58)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:57)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:71)
	at br.com.caelum.vraptor.core.URLParameterExtractorInterceptor.intercept(URLParameterExtractorInterceptor.java:45)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:57)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:71)
	at br.com.caelum.vraptor.interceptor.ResourceLookupInterceptor.intercept(ResourceLookupInterceptor.java:70)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:57)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:71)
	at br.com.caelum.vraptor.core.DefaultRequestExecution.execute(DefaultRequestExecution.java:71)
	at br.com.caelum.vraptor.VRaptor$1.insideRequest(VRaptor.java:99)
	at br.com.caelum.vraptor.ioc.spring.SpringProvider.provideForRequest(SpringProvider.java:37)
	at br.com.caelum.vraptor.VRaptor.doFilter(VRaptor.java:97)
	at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1084)
	at com.google.apphosting.runtime.jetty.SaveSessionFilter.doFilter(SaveSessionFilter.java:35)
	at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1084)
	at com.google.apphosting.utils.servlet.TransactionCleanupFilter.doFilter(TransactionCleanupFilter.java:43)
	at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1084)
	at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:360)
	at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
	at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:181)
	at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:712)
	at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:405)
	at com.google.apphosting.runtime.jetty.AppVersionHandlerMap.handle(AppVersionHandlerMap.java:237)
	at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:139)
	at org.mortbay.jetty.Server.handle(Server.java:313)
	at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:506)
	at org.mortbay.jetty.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:830)
	at com.google.apphosting.runtime.jetty.RpcRequestParser.parseAvailable(RpcRequestParser.java:76)
	at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:381)
	at com.google.apphosting.runtime.jetty.JettyServletEngineAdapter.serviceRequest(JettyServletEngineAdapter.java:139)
	at com.google.apphosting.runtime.JavaRuntime.handleRequest(JavaRuntime.java:235)
	at com.google.apphosting.base.RuntimePb$EvaluationRuntime$6.handleBlockingRequest(RuntimePb.java:4950)
	at com.google.apphosting.base.RuntimePb$EvaluationRuntime$6.handleBlockingRequest(RuntimePb.java:4948)
	at com.google.net.rpc.impl.BlockingApplicationHandler.handleRequest(BlockingApplicationHandler.java:24)
	at com.google.net.rpc.impl.RpcUtil.runRpcInApplication(RpcUtil.java:359)
	at com.google.net.rpc.impl.Server$2.run(Server.java:823)
	at com.google.tracing.LocalTraceSpanRunnable.run(LocalTraceSpanRunnable.java:56)
	at com.google.tracing.LocalTraceSpanBuilder.internalContinueSpan(LocalTraceSpanBuilder.java:516)
	at com.google.net.rpc.impl.Server.startRpc(Server.java:778)
	at com.google.net.rpc.impl.Server.processRequest(Server.java:351)
	at com.google.net.rpc.impl.ServerConnection.messageReceived(ServerConnection.java:437)
	at com.google.net.rpc.impl.RpcConnection.parseMessages(RpcConnection.java:319)
	at com.google.net.rpc.impl.RpcConnection.dataReceived(RpcConnection.java:290)
	at com.google.net.async.Connection.handleReadEvent(Connection.java:428)
	at com.google.net.async.EventDispatcher.processNetworkEvents(EventDispatcher.java:762)
	at com.google.net.async.EventDispatcher.internalLoop(EventDispatcher.java:207)
	at com.google.net.async.EventDispatcher.loop(EventDispatcher.java:101)
	at com.google.net.rpc.RpcService.runUntilServerShutdown(RpcService.java:251)
	at com.google.apphosting.runtime.JavaRuntime$RpcRunnable.run(JavaRuntime.java:392)
	at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.NullPointerException
	at br.med.scp.repository.impl.PersistenceHelper.list(PersistenceHelper.java:126)
	at br.med.scp.repository.impl.CidsImpl.list(CidsImpl.java:33)
	at br.med.scp.controller.CidController.index(CidController.java:43)
	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(Method.java:40)
	at br.com.caelum.vraptor.interceptor.ExecuteMethodInterceptor.intercept(ExecuteMethodInterceptor.java:59)
	... 62 more

Meu construtor

	public CidController(Repositories repositories, EntityTransaction transaction, Result result) {
		this.cids = repositories.getCids();
		this.result = result;
		this.transaction = transaction;
	}

O NPE pelo que entendi ele não está passando as dependencias, quando eu faço na mão e não dependo da injeção de dependencias funciona, mas aí perde a graça, hehehe.

[]s

at br.med.scimpac.repository.impl.PersistenceHelper.list(PersistenceHelper.java:126)

e esse metodo list da persistencehelper, na linha 126? o que tem nela? posta o codigo da classe?

@Paulo Silveira

Foi o primeiro lugar que eu fui ver

	@SuppressWarnings("unchecked")
	public static &lt;E&gt; List&lt;E&gt; list(EntityManager em, Class&lt;E&gt; klass) {
		Query query = em.createQuery("select e from "+klass.getName()+" e");
		return query.getResultList();
	}

Ele está recebendo null no EntityManager

Um apanhado das classes

@Component 
public class RepositoriesImpl implements Repositories {
	private EntityManager em;

	public RepositoriesImpl(EntityManager em) {
		this.em = em;
	}

	@Override
	public Cids getCids() {
		return new CidsImpl(this.em);
	}
(...)
@Resource
public class CidController {
	private Cids cids;

	public CidController(Repositories repositories) {
		this.cids = repositories.getCids();
        }
(...)
	@Path("/cids")
	public List&lt;Cid&gt; index() {
		return this.cids.list();
	}
public class CidsImpl implements Cids {
	private EntityManager em;
	private PersistenceHelper&lt;Cid&gt; ph;

	public CidsImpl(EntityManager em) {
		this.em = em;
		this.ph = PersistenceHelper.forEntity(em, Cid.class);
	}

	@Override
	public List&lt;Cid&gt; list() {
		return PersistenceHelper.list(this.em, Cid.class);
	}

[]s

oi edufa!

é, ele esta inserindo null no seu construtor do CidsImpl. Consegue dar mais detalhes? Voce tem um provider pra EntityManager?

Isso parece vir de antes: o RepositoriesImpl esta recebendo null no seu contrutor que recebe EntityManager. Sera que seu provider esta fabricando null para injetar? Onde esta ele?

@Paulo Silveira

Olá, pois é, aqui está o codigo do que cria o EntityManagerFactory

@ApplicationScoped
@Component
public class EntityManagerFactoryCreator implements ComponentFactory&lt;EntityManagerFactory&gt; {
	private final EntityManagerFactory factory;
 
	public EntityManagerFactoryCreator() {
		this.factory = PersistenceHelper.getEntityManagerFactory();
	}
 
	public EntityManagerFactory getInstance() {
		return this.factory;
	}
 
	@PreDestroy
	public void destroy() {
		if (this.factory.isOpen())
			this.factory.close();
	}
 
}

E o EntityManager

@RequestScoped
@Component
public class EntityManagerCreator implements ComponentFactory&lt;EntityManager&gt; {
	private final EntityManagerFactory factory;
	private EntityManager session;
 
	public EntityManagerCreator(EntityManagerFactory factory) {
		this.factory = factory;
	}
 
	@PostConstruct
	public void create() {
		this.session = factory.createEntityManager();
	}
 
	@Override
	public EntityManager getInstance() {
		return this.session;
	}
 
	@PreDestroy
	public void destroy() {
		if (this.session != null && this.session.isOpen())
			this.session.close();
	}
 
}

[]s

Edufa!

Sera que ele esta criando o EntityManager corretamente?

Na linha 13 do EntityManagerCreator:
this.session = factory.createEntityManager();

Coloque loggers ntes e depois, pra ver se o metodo esta sendo invocado, e se a factory esta devolvendo algo diferente de null (ou ainda se nao esta subindo uma exception!)

abracos

Olá Paulo Silveira

Aqui o codigo modificado, com o log


	public EntityManagerCreator(EntityManagerFactory factory) {
		this.factory = factory;
		log.info("EntityManagerCreator.constructor :: Factory: "+factory);
                // chamou, aqui o log do GAE
                // br.med.scp.infra.vraptor.EntityManagerCreator &lt;init&gt;: EntityManagerCreator.constructor :: Factory: org.datanucleus.store.appengine.jpa.DatastoreEntityManagerFactory@6c9220
	}
 
	@PostConstruct
	public void create() {
		log.info(&quot;EntityManagerCreator.create :: Before -&gt; Factory: &quot;+factory);
		try {
			this.session = factory.createEntityManager();
		} catch (Exception e) {
			log.info(&quot;EntityManagerCreator.create :: Exception: &quot;+e);
		}
		log.info(&quot;EntityManagerCreator.create :: After -&gt; Session: &quot;+this.session);
	}

Ele carrega o EntityManagerCreator, com a EntityManagerFactory.

Mas não chamou o @PostConstruct create.

[]s !!

Isso tá acontecendo localmente também ou soh no GAE?

com o jar do spring inteiro funciona… será que vc não esqueceu de colocar um dos jars que é o que
trata dessa parte de @PostConstruct e @PreDestroy
(não é o VRaptor que cuida disso… ele deixa esse processamento pro container de IoC)

[]'s

Olá lucascs

Só no GAE,
Localmente tá funcionando perfeito

Tenho de dar uma olhada com mais calma, eu usei o jar que veio junto com o vraptor, mas ele tinha problemas com a java.lang.NoClassDefFoundError: javax/naming/NamingException , eu removi o pacote orm e parou de dar, só se a parte do @PostConstruct tivesse alguma relação com esse pacote.

Eu retirei o @PostConstruct, e instanciei a EntityManager no construtor mesmo e funcionou, vou dar uma olhada se mais alguem tem reclamado do @PostConstruct no GAE.

	public EntityManagerCreator(EntityManagerFactory factory) {
		this.factory = factory;
		this.em = factory.createEntityManager();
		log.info("EntityManagerCreator.constructor :: Factory: "+factory);
	}

Obrigado pela ajuda até aqui !

[]s!

sera que o listener do Spring ta tentando abrir thread?
voces viram se esse jar em especifico ta na white list do GAE?

o jar do spring inteiro tenta fazer alguma coisa que usa javax.naming eh javax.naming eh banido do appengine. tem que ficar sem ele mesmo. tem que ser jar picado… aqui estamos com esses no gae:
spring-beans,context,core e web. so esses 4 rola?

guilherme, eh bom documentar esses jars necessarios no repsoitorio do vraptor. ou lucas!